soulsync/webui/src/app/api-client.test.ts
Antti Kettunen ce1fb16b76
Split webui tooling into separate configs
- Move Vite, Vitest, Oxfmt, and Oxlint into standalone config files
- Replace vite-plus scripts and test imports with direct tools
- Keep the generated route tree out of formatter and linter checks
2026-05-13 22:26:25 +03:00

50 lines
1.7 KiB
TypeScript

import type { ResponsePromise } from 'ky';
import { HTTPError } from 'ky';
import { describe, expect, it, vi } from 'vitest';
import { readJson } from './api-client';
function createHttpError(body: unknown, status = 400) {
const response = new Response(JSON.stringify(body), {
status,
statusText: 'Bad Request',
headers: {
'Content-Type': 'application/json',
},
});
const request = new Request('https://example.com/api/test');
const error = new HTTPError(response, request, {} as any);
error.data = body;
return error;
}
describe('readJson', () => {
it('returns parsed JSON', async () => {
const json = vi.fn().mockResolvedValue({ ok: true });
const promise = { json } as unknown as ResponsePromise<{ ok: boolean }>;
await expect(readJson(promise)).resolves.toEqual({ ok: true });
expect(json).toHaveBeenCalledTimes(1);
});
it('keeps HTTPError instances intact and uses the payload message', async () => {
const error = createHttpError({ error: 'Nope' }, 403);
const json = vi.fn().mockRejectedValue(error);
const promise = { json } as unknown as ResponsePromise<unknown>;
const result = readJson(promise);
await expect(result).rejects.toBe(error);
await expect(result).rejects.toHaveProperty('message', 'Nope');
});
it('falls back to the HTTPError message when the payload is unhelpful', async () => {
const error = createHttpError({ detail: 'missing error field' }, 404);
const json = vi.fn().mockRejectedValue(error);
const promise = { json } as unknown as ResponsePromise<unknown>;
const result = readJson(promise);
await expect(result).rejects.toBe(error);
await expect(result).rejects.toHaveProperty('message', error.message);
});
});