76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import { api, ApiError, errorMessage } from '../apiClient.ts';
|
|
|
|
const jsonResponse = (body: unknown, status = 200, headers: Record<string, string> = {}) =>
|
|
new Response(JSON.stringify(body), {
|
|
status,
|
|
headers: { 'Content-Type': 'application/json', ...headers },
|
|
});
|
|
|
|
describe('apiClient', () => {
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals();
|
|
document.cookie = 'csrftoken=; Max-Age=0; path=/';
|
|
});
|
|
|
|
it('unwraps paginated list results', async () => {
|
|
vi.stubGlobal(
|
|
'fetch',
|
|
vi.fn().mockResolvedValue(
|
|
jsonResponse({
|
|
count: 1,
|
|
next: null,
|
|
previous: null,
|
|
results: [{ id: 7, site_name: 'Sukawarna', user: 1 }],
|
|
})
|
|
)
|
|
);
|
|
|
|
const sites = await api.sites.list();
|
|
expect(sites).toEqual([{ id: 7, site_name: 'Sukawarna', user: 1 }]);
|
|
});
|
|
|
|
it('unwraps a bare array list', async () => {
|
|
vi.stubGlobal(
|
|
'fetch',
|
|
vi.fn().mockResolvedValue(jsonResponse([{ id: 2, site_name: 'Cilayang', user: 1 }]))
|
|
);
|
|
|
|
const sites = await api.sites.list();
|
|
expect(sites[0]?.site_name).toBe('Cilayang');
|
|
});
|
|
|
|
it('sends CSRF token on POST', async () => {
|
|
document.cookie = 'csrftoken=abc123; path=/';
|
|
const fetchMock = vi.fn().mockResolvedValue(jsonResponse({ id: 1, user_name: 'admin', display_name: 'Admin' }));
|
|
vi.stubGlobal('fetch', fetchMock);
|
|
|
|
await api.auth.login('admin', 'admin123');
|
|
|
|
const init = fetchMock.mock.calls[0]?.[1] as RequestInit;
|
|
const headers = new Headers(init.headers);
|
|
expect(headers.get('X-CSRFToken')).toBe('abc123');
|
|
expect(init.credentials).toBe('include');
|
|
});
|
|
|
|
it('throws ApiError with detail and status', async () => {
|
|
document.cookie = 'csrftoken=abc123; path=/';
|
|
vi.stubGlobal(
|
|
'fetch',
|
|
vi.fn().mockResolvedValue(jsonResponse({ detail: 'Bad credentials' }, 400))
|
|
);
|
|
|
|
await expect(api.auth.login('x', 'y')).rejects.toMatchObject({
|
|
name: 'ApiError',
|
|
status: 400,
|
|
message: 'Bad credentials',
|
|
});
|
|
});
|
|
|
|
it('maps unknown errors through errorMessage', () => {
|
|
expect(errorMessage(new ApiError('Gagal', 502, null))).toBe('Gagal');
|
|
expect(errorMessage(new Error('boom'))).toBe('boom');
|
|
expect(errorMessage('nope')).toBe('Terjadi kesalahan');
|
|
});
|
|
});
|