import { describe, it, expect, vi, beforeEach } from "vitest"; vi.mock("./config.js", () => ({ getConfig: vi.fn(() => ({ apiUrl: "https://api.skills-hub.ai" })), getAuthHeader: vi.fn(() => ({ Authorization: "Bearer test-token" })), })); import { apiRequest } from "./api-client.js"; const mockFetch = vi.fn(); global.fetch = mockFetch; beforeEach(() => { vi.clearAllMocks(); }); describe("apiRequest", () => { it("makes request with correct URL and headers", async () => { mockFetch.mockResolvedValue({ ok: true, json: () => Promise.resolve({ data: "test" }), }); await apiRequest("/api/v1/skills"); expect(mockFetch).toHaveBeenCalledWith( "https://api.skills-hub.ai/api/v1/skills", expect.objectContaining({ headers: expect.objectContaining({ "Content-Type": "application/json", Authorization: "Bearer test-token", }), }), ); }); it("returns parsed JSON on success", async () => { mockFetch.mockResolvedValue({ ok: true, json: () => Promise.resolve({ id: "123" }), }); const result = await apiRequest("/api/v1/skills"); expect(result).toEqual({ id: "123" }); }); it("throws error with API message on failure", async () => { mockFetch.mockResolvedValue({ ok: false, status: 404, json: () => Promise.resolve({ error: { message: "Skill not found" } }), }); await expect(apiRequest("/api/v1/skills/missing")).rejects.toThrow( "Skill not found", ); }); it("throws generic error when no message in body", async () => { mockFetch.mockResolvedValue({ ok: false, status: 500, json: () => Promise.reject(new Error("parse error")), }); await expect(apiRequest("/api/v1/skills")).rejects.toThrow( "API error: 500", ); }); it("passes custom options through", async () => { mockFetch.mockResolvedValue({ ok: true, json: () => Promise.resolve({}), }); await apiRequest("/api/v1/skills", { method: "POST", body: '{"name":"test"}', }); expect(mockFetch).toHaveBeenCalledWith( expect.any(String), expect.objectContaining({ method: "POST", body: '{"name":"test"}' }), ); }); });