let jobsApi: any let companiesApi: any let usersApi: any // Mock environment variable const ORIGINAL_ENV = process.env beforeEach(() => { jest.resetModules() process.env = { ...process.env, NEXT_PUBLIC_API_URL: 'http://test-api.com/api/v1' } // Re-require modules to pick up new env vars const api = require('../api') jobsApi = api.jobsApi companiesApi = api.companiesApi usersApi = api.usersApi global.fetch = jest.fn() }) afterEach(() => { jest.clearAllMocks() }) afterAll(() => { process.env = ORIGINAL_ENV }) describe('API Client', () => { describe('jobsApi', () => { it('should fetch jobs with correct parameters', async () => { const mockJobs = { data: [{ id: 1, title: 'Dev Job' }], pagination: { total: 1 } } ; (global.fetch as jest.Mock).mockResolvedValueOnce({ ok: true, json: async () => mockJobs, }) const response = await jobsApi.list({ page: 1, limit: 10, companyId: 5 }) expect(global.fetch).toHaveBeenCalledWith( 'http://test-api.com/api/v1/jobs?page=1&limit=10&companyId=5', expect.objectContaining({ headers: expect.objectContaining({ 'Content-Type': 'application/json' }) }) ) expect(response).toEqual(mockJobs) }) it('should handle API errors correctly', async () => { ; (global.fetch as jest.Mock).mockResolvedValueOnce({ ok: false, status: 404, text: async () => 'Not Found', }) await expect(jobsApi.list()).rejects.toThrow('Not Found') }) }) describe('companiesApi', () => { it('should create company correctly', async () => { const mockCompany = { id: '123', name: 'Test Corp' } ; (global.fetch as jest.Mock).mockResolvedValueOnce({ ok: true, json: async () => mockCompany, }) const newCompany = { name: 'Test Corp', slug: 'test-corp' } await companiesApi.create(newCompany) expect(global.fetch).toHaveBeenCalledWith( 'http://test-api.com/api/v1/companies', expect.objectContaining({ method: 'POST', body: JSON.stringify(newCompany) }) ) }) }) describe('URL Construction', () => { it('should handle double /api/v1 correctly', async () => { ; (global.fetch as jest.Mock).mockResolvedValueOnce({ ok: true, json: async () => ([]), }) // We need to import the raw apiRequest function to test this properly, // but since it's not exported, we simulate via an exported function await usersApi.list() // The apiRequest logic handles URL cleaning. // Expected: base http://test-api.com/api/v1 + endpoint /api/v1/users -> http://test-api.com/api/v1/users // NOT http://test-api.com/api/v1/api/v1/users expect(global.fetch).toHaveBeenCalledWith( 'http://test-api.com/api/v1/users', expect.any(Object) ) }) }) })