40 lines
2.4 KiB
TypeScript
40 lines
2.4 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import { ApiProblemError, requestJSON } from '../../src/apiClient';
|
|
|
|
afterEach(() => vi.unstubAllGlobals());
|
|
|
|
describe('requestJSON', () => {
|
|
it('preserves safe problem and correlation context', async () => {
|
|
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response(JSON.stringify({ title: 'Begrensd', detail: 'Probeer een kortere periode.' }), { status: 422, headers: { 'content-type': 'application/problem+json', 'x-correlation-id': 'corr-123' } })));
|
|
await expect(requestJSON('/api/v1/example')).rejects.toMatchObject({ status: 422, correlationId: 'corr-123', message: 'Probeer een kortere periode.' } satisfies Partial<ApiProblemError>);
|
|
});
|
|
|
|
it('retries safe GET requests only within the configured bound', async () => {
|
|
const fetcher = vi.fn().mockResolvedValueOnce(new Response('{}', { status: 503 })).mockResolvedValueOnce(new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'content-type': 'application/json' } }));
|
|
vi.stubGlobal('fetch', fetcher);
|
|
await expect(requestJSON<{ ok: boolean }>('/api/v1/example', { retries: 1 })).resolves.toEqual({ ok: true });
|
|
expect(fetcher).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it('never retries mutations', async () => {
|
|
const fetcher = vi.fn().mockResolvedValue(new Response('{}', { status: 503, headers: { 'content-type': 'application/problem+json' } }));
|
|
vi.stubGlobal('fetch', fetcher);
|
|
await expect(requestJSON('/api/v1/example', { method: 'POST', retries: 2 })).rejects.toBeInstanceOf(ApiProblemError);
|
|
expect(fetcher).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it.each([401, 403])('preserves authorization status %s without retry', async (status) => {
|
|
const fetcher = vi.fn().mockResolvedValue(new Response(JSON.stringify({ title: 'Geen toegang', correlationId: 'corr-auth' }), { status, headers: { 'content-type': 'application/problem+json' } }));
|
|
vi.stubGlobal('fetch', fetcher);
|
|
await expect(requestJSON('/api/v1/protected', { retries: 2 })).rejects.toMatchObject({ status, correlationId: 'corr-auth' });
|
|
expect(fetcher).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('never retries an aborted request', async () => {
|
|
const fetcher = vi.fn().mockRejectedValue(new DOMException('aborted', 'AbortError'));
|
|
vi.stubGlobal('fetch', fetcher);
|
|
await expect(requestJSON('/api/v1/example', { retries: 2 })).rejects.toMatchObject({ name: 'AbortError' });
|
|
expect(fetcher).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|