/** * Integration Test: ApiClient * * Tests the ApiClient infrastructure for making HTTP requests */ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { ApiClient } from '../api-client'; describe('ApiClient - Infrastructure Tests', () => { let apiClient: ApiClient; let mockServer: { close: () => void; port: number }; beforeAll(async () => { // Create a mock HTTP server for testing const http = require('http'); const server = http.createServer((req: any, res: any) => { if (req.url === '/health') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ status: 'ok' })); } else if (req.url === '/api/data') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'success', data: { id: 1, name: 'test' } })); } else if (req.url === '/api/error') { res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'Internal Server Error' })); } else if (req.url === '/api/slow') { // Simulate slow response setTimeout(() => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'slow response' })); }, 2000); } else { res.writeHead(404); res.end('Not Found'); } }); await new Promise((resolve) => { server.listen(0, () => { const port = (server.address() as any).port; mockServer = { close: () => server.close(), port }; apiClient = new ApiClient({ baseUrl: `http://localhost:${port}`, timeout: 5000 }); resolve(); }); }); }); afterAll(() => { if (mockServer) { mockServer.close(); } }); describe('HTTP Methods', () => { it('should successfully make a GET request', async () => { const result = await apiClient.get<{ message: string; data: { id: number; name: string } }>('/api/data'); expect(result.message).toBe('success'); expect(result.data.id).toBe(1); }); it('should successfully make a POST request with body', async () => { const result = await apiClient.post<{ message: string }>('/api/data', { name: 'test' }); expect(result.message).toBe('success'); }); it('should successfully make a PUT request with body', async () => { const result = await apiClient.put<{ message: string }>('/api/data', { id: 1 }); expect(result.message).toBe('success'); }); it('should successfully make a PATCH request with body', async () => { const result = await apiClient.patch<{ message: string }>('/api/data', { name: 'patched' }); expect(result.message).toBe('success'); }); it('should successfully make a DELETE request', async () => { const result = await apiClient.delete<{ message: string }>('/api/data'); expect(result.message).toBe('success'); }); }); describe('Error Handling & Timeouts', () => { it('should handle HTTP errors gracefully', async () => { await expect(apiClient.get('/api/error')).rejects.toThrow('API Error 500'); }); it('should handle timeout errors', async () => { const shortTimeoutClient = new ApiClient({ baseUrl: `http://localhost:${mockServer.port}`, timeout: 100, }); await expect(shortTimeoutClient.get('/api/slow')).rejects.toThrow('Request timeout after 100ms'); }); }); describe('Health & Readiness', () => { it('should successfully check health endpoint', async () => { expect(await apiClient.health()).toBe(true); }); it('should wait for API to be ready', async () => { await apiClient.waitForReady(5000); expect(true).toBe(true); }); }); });