66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
|
|
import { describe, expect, it, vi } from 'vitest';
|
||
|
|
|
||
|
|
import { ApiError, request } from '@/api/client';
|
||
|
|
|
||
|
|
function jsonResponse(body: unknown, status = 200): Response {
|
||
|
|
return new Response(JSON.stringify(body), {
|
||
|
|
status,
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
describe('api client', () => {
|
||
|
|
it('returns the parsed payload on success', async () => {
|
||
|
|
const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ api_version: 'v1' }));
|
||
|
|
vi.stubGlobal('fetch', fetchMock);
|
||
|
|
|
||
|
|
await expect(request<{ api_version: string }>('/meta')).resolves.toEqual({
|
||
|
|
api_version: 'v1',
|
||
|
|
});
|
||
|
|
expect(fetchMock).toHaveBeenCalledWith(
|
||
|
|
'/api/v1/meta',
|
||
|
|
expect.objectContaining({ method: 'GET', credentials: 'same-origin' }),
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('maps the server error envelope to ApiError', async () => {
|
||
|
|
vi.stubGlobal(
|
||
|
|
'fetch',
|
||
|
|
vi
|
||
|
|
.fn()
|
||
|
|
.mockResolvedValue(
|
||
|
|
jsonResponse({ error: { code: 'perm.denied', message: 'no access' } }, 403),
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
await expect(request('/guilds/1')).rejects.toMatchObject({
|
||
|
|
name: 'ApiError',
|
||
|
|
code: 'perm.denied',
|
||
|
|
status: 403,
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('falls back to internal.error when the body is not an envelope', async () => {
|
||
|
|
vi.stubGlobal(
|
||
|
|
'fetch',
|
||
|
|
vi.fn().mockResolvedValue(new Response('gateway timeout', { status: 504 })),
|
||
|
|
);
|
||
|
|
|
||
|
|
const error = await request('/meta').catch((reason: unknown) => reason);
|
||
|
|
expect(error).toBeInstanceOf(ApiError);
|
||
|
|
expect((error as ApiError).code).toBe('internal.error');
|
||
|
|
expect((error as ApiError).status).toBe(504);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('sends a json body for write requests', async () => {
|
||
|
|
const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ ok: true }));
|
||
|
|
vi.stubGlobal('fetch', fetchMock);
|
||
|
|
|
||
|
|
await request('/guilds', { method: 'POST', body: { name: 'test' } });
|
||
|
|
|
||
|
|
const init = fetchMock.mock.calls[0]?.[1] as RequestInit;
|
||
|
|
expect(init.body).toBe('{"name":"test"}');
|
||
|
|
expect((init.headers as Record<string, string>)['Content-Type']).toBe('application/json');
|
||
|
|
});
|
||
|
|
});
|