import { describe, it, expect, vi, beforeEach } from 'vitest' import { apiFetch } from './http' describe('apiFetch', () => { beforeEach(() => { vi.restoreAllMocks() }) it('sets Content-Type to application/json by default', async () => { const spy = vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, status: 200, json: () => Promise.resolve({ data: 1 }), }) await apiFetch('/api/test') expect(spy).toHaveBeenCalledWith( '/api/test', expect.objectContaining({ headers: expect.objectContaining({ 'Content-Type': 'application/json' }), }), ) }) it('skips Content-Type when skipContentType is true', async () => { const spy = vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, status: 200, json: () => Promise.resolve({}), }) await apiFetch('/api/upload', { skipContentType: true }) const headers = spy.mock.calls[0][1].headers expect(headers['Content-Type']).toBeUndefined() }) it('returns parsed JSON on success', async () => { vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, status: 200, json: () => Promise.resolve({ id: '123', name: 'doc.pdf' }), }) const result = await apiFetch('/api/docs') expect(result).toEqual({ id: '123', name: 'doc.pdf' }) }) it('returns null on 204 No Content', async () => { vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, status: 204, }) const result = await apiFetch('/api/docs/1', { method: 'DELETE' }) expect(result).toBeNull() }) it('throws on non-ok response', async () => { vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: false, status: 404, }) await expect(apiFetch('/api/docs/missing')).rejects.toThrow('API error: 404') }) it('forwards method and body options', async () => { const spy = vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, status: 200, json: () => Promise.resolve({}), }) const body = JSON.stringify({ documentId: '42' }) await apiFetch('/api/analyses', { method: 'POST', body }) expect(spy).toHaveBeenCalledWith( '/api/analyses', expect.objectContaining({ method: 'POST', body, }), ) }) it('merges custom headers with Content-Type', async () => { const spy = vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: true, status: 200, json: () => Promise.resolve({}), }) await apiFetch('/api/test', { headers: { 'X-Custom': 'value' } }) const headers = spy.mock.calls[0][1].headers expect(headers['Content-Type']).toBe('application/json') expect(headers['X-Custom']).toBe('value') }) })