feat(web): auto-logout on 401 inside apiFetch
Dynamic import breaks the apiFetch <-> auth/store cycle. silent:true prevents re-POSTing /logout against an already-dead session.
This commit is contained in:
@@ -79,3 +79,24 @@ describe('api.get/post/del', () => {
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('apiFetch 401 interceptor', () => {
|
||||
test('401 response triggers auth.logout({silent:true}) and still throws', async () => {
|
||||
const logoutSpy = vi.fn();
|
||||
vi.doMock('$lib/auth/store.svelte', () => ({
|
||||
logout: logoutSpy,
|
||||
login: vi.fn(),
|
||||
bootstrap: vi.fn(),
|
||||
user: { value: null }
|
||||
}));
|
||||
// Re-import to pick up the mock.
|
||||
const { apiFetch: apiFetchFresh } = await import('./client');
|
||||
stubFetch(401, { error: { code: 'unauthorized', message: 'session expired' } });
|
||||
await expect(apiFetchFresh('/api/me')).rejects.toMatchObject({
|
||||
code: 'unauthorized',
|
||||
status: 401
|
||||
});
|
||||
expect(logoutSpy).toHaveBeenCalledWith({ silent: true });
|
||||
vi.doUnmock('$lib/auth/store.svelte');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user