import { describe, it, expect, vi, beforeEach } from 'vitest'; vi.mock('$lib/shared/api.server', () => ({ createApiClient: vi.fn(), extractErrorCode: (e: unknown) => (e as { code?: string } | undefined)?.code })); import { load } from './+page.server'; import { createApiClient } from '$lib/shared/api.server'; import { getErrorMessage } from '$lib/shared/errors'; beforeEach(() => vi.clearAllMocks()); const TIMELINE = { years: [{ year: 1914, entries: [] }], undated: [] }; function mockApi(opts: { ok?: boolean; status?: number; data?: unknown; error?: unknown }) { const { ok = true, status = 200, data = TIMELINE, error } = opts; const GET = vi.fn().mockResolvedValue({ response: { ok, status }, data: ok ? data : undefined, error }); vi.mocked(createApiClient).mockReturnValue({ GET } as unknown as ReturnType< typeof createApiClient >); return GET; } function callLoad() { return load({ fetch: vi.fn() as unknown as typeof fetch, url: new URL('http://localhost/zeitstrahl'), request: new Request('http://localhost/zeitstrahl'), route: { id: '/zeitstrahl' }, params: {} } as unknown as Parameters[0]); } describe('zeitstrahl +page.server load', () => { it('fetches GET /api/timeline and returns { timeline } on ok (REQ-001/002)', async () => { const GET = mockApi({ data: TIMELINE }); const result = await callLoad(); expect(GET).toHaveBeenCalledWith('/api/timeline'); expect(result).toEqual({ timeline: TIMELINE }); }); it('redirects to /login on 401 (REQ-022)', async () => { mockApi({ ok: false, status: 401 }); await expect(callLoad()).rejects.toMatchObject({ status: 302, location: '/login' }); }); it('throws a mapped error on 404 (REQ-022)', async () => { mockApi({ ok: false, status: 404, error: { code: 'TIMELINE_EVENT_NOT_FOUND' } }); await expect(callLoad()).rejects.toMatchObject({ status: 404, body: { message: getErrorMessage('TIMELINE_EVENT_NOT_FOUND') } }); }); it('throws a mapped error on 500 (REQ-022)', async () => { mockApi({ ok: false, status: 500, error: undefined }); await expect(callLoad()).rejects.toMatchObject({ status: 500 }); }); it('throws a mapped FORBIDDEN error on 403 (REQ-022)', async () => { mockApi({ ok: false, status: 403, error: { code: 'FORBIDDEN' } }); await expect(callLoad()).rejects.toMatchObject({ status: 403, body: { message: getErrorMessage('FORBIDDEN') } }); }); });