import { describe, it, expect, beforeAll, afterEach, afterAll } from 'vitest'; import { setupServer } from 'msw/node'; import { http, HttpResponse } from 'msw'; import { listProviders, createProvider, updateProvider, deleteProvider } from '@/api/providers'; const mockProviders = [ { id: 'prov-1', name: 'OpenAI', api_key: 'sk-xxx', base_url: 'https://api.openai.com', protocol: 'openai', enabled: true, created_at: '2025-01-01T00:00:00Z', updated_at: '2025-01-01T00:00:00Z', }, { id: 'prov-2', name: 'Anthropic', api_key: 'sk-yyy', base_url: 'https://api.anthropic.com', protocol: 'anthropic', enabled: false, created_at: '2025-01-02T00:00:00Z', updated_at: '2025-01-02T00:00:00Z', }, ]; describe('providers API', () => { const server = setupServer(); beforeAll(() => server.listen({ onUnhandledRequest: 'bypass' })); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); describe('listProviders', () => { it('returns array of Provider objects with camelCase keys', async () => { server.use( http.get('http://localhost:3000/api/providers', () => { return HttpResponse.json(mockProviders); }), ); const result = await listProviders(); expect(result).toEqual([ { id: 'prov-1', name: 'OpenAI', apiKey: 'sk-xxx', baseUrl: 'https://api.openai.com', protocol: 'openai', enabled: true, createdAt: '2025-01-01T00:00:00Z', updatedAt: '2025-01-01T00:00:00Z', }, { id: 'prov-2', name: 'Anthropic', apiKey: 'sk-yyy', baseUrl: 'https://api.anthropic.com', protocol: 'anthropic', enabled: false, createdAt: '2025-01-02T00:00:00Z', updatedAt: '2025-01-02T00:00:00Z', }, ]); }); }); describe('createProvider', () => { it('sends POST with correct body and returns provider', async () => { let receivedMethod: string | null = null; let receivedBody: Record | null = null; server.use( http.post('http://localhost:3000/api/providers', async ({ request }) => { receivedMethod = request.method; receivedBody = (await request.json()) as Record; return HttpResponse.json(mockProviders[0]); }), ); const input = { id: 'prov-1', name: 'OpenAI', apiKey: 'sk-xxx', baseUrl: 'https://api.openai.com', enabled: true, }; const result = await createProvider(input); expect(receivedMethod).toBe('POST'); expect(receivedBody).toEqual({ id: 'prov-1', name: 'OpenAI', api_key: 'sk-xxx', base_url: 'https://api.openai.com', enabled: true, }); expect(result).toEqual({ id: 'prov-1', name: 'OpenAI', apiKey: 'sk-xxx', baseUrl: 'https://api.openai.com', protocol: 'openai', enabled: true, createdAt: '2025-01-01T00:00:00Z', updatedAt: '2025-01-01T00:00:00Z', }); }); }); describe('updateProvider', () => { it('sends PUT with correct body and returns provider', async () => { let receivedMethod: string | null = null; let receivedUrl: string | null = null; let receivedBody: Record | null = null; server.use( http.put('http://localhost:3000/api/providers/:id', async ({ request, params }) => { receivedMethod = request.method; receivedUrl = new URL(request.url).pathname; receivedBody = (await request.json()) as Record; return HttpResponse.json({ ...mockProviders[0], name: 'Updated', api_key: 'sk-updated', }); }), ); const result = await updateProvider('prov-1', { name: 'Updated', apiKey: 'sk-updated', }); expect(receivedMethod).toBe('PUT'); expect(receivedUrl).toBe('/api/providers/prov-1'); expect(receivedBody).toEqual({ name: 'Updated', api_key: 'sk-updated', }); expect(result.name).toBe('Updated'); expect(result.apiKey).toBe('sk-updated'); }); }); describe('deleteProvider', () => { it('sends DELETE and returns void', async () => { let receivedMethod: string | null = null; let receivedUrl: string | null = null; server.use( http.delete('http://localhost:3000/api/providers/:id', ({ request, params }) => { receivedMethod = request.method; receivedUrl = new URL(request.url).pathname; return new HttpResponse(null, { status: 204 }); }), ); const result = await deleteProvider('prov-1'); expect(receivedMethod).toBe('DELETE'); expect(receivedUrl).toBe('/api/providers/prov-1'); expect(result).toBeUndefined(); }); }); });