import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; const mocks = vi.hoisted(() => ({ getApiKeys: vi.fn(), getConsistentMachineId: vi.fn(), })); vi.mock("@/lib/localDb", () => ({ getApiKeys: mocks.getApiKeys, })); vi.mock("@/shared/utils/machineId", () => ({ getConsistentMachineId: mocks.getConsistentMachineId, })); vi.mock("next/server", () => ({ NextResponse: { json(body, init = {}) { return new Response(JSON.stringify(body), { status: init.status || 200, headers: { "Content-Type": "application/json" }, }); }, }, })); const originalFetch = global.fetch; describe("model test route kind routing", () => { beforeEach(() => { vi.clearAllMocks(); mocks.getApiKeys.mockResolvedValue([{ key: "sk-internal", isActive: true }]); mocks.getConsistentMachineId.mockResolvedValue("cli-token"); global.fetch = vi.fn().mockResolvedValue(new Response(JSON.stringify({ created: 1, data: [{ b64_json: "abc" }], }), { status: 200, headers: { "Content-Type": "application/json" }, })); }); afterEach(() => { global.fetch = originalFetch; }); it("routes image model tests to /api/v1/images/generations", async () => { const { POST } = await import("../../src/app/api/models/test/route.js"); const req = new Request("http://localhost/api/models/test", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "hf/black-forest-labs/FLUX.1-schnell", kind: "image", }), }); const res = await POST(req); const body = await res.json(); expect(body.ok).toBe(true); expect(global.fetch).toHaveBeenCalledWith( expect.stringContaining("/api/v1/images/generations"), expect.objectContaining({ method: "POST", body: JSON.stringify({ model: "hf/black-forest-labs/FLUX.1-schnell", prompt: "test", }), }) ); }); it("routes embedding model tests to /api/v1/embeddings", async () => { global.fetch = vi.fn().mockResolvedValue(new Response(JSON.stringify({ data: [{ embedding: [0.1, 0.2] }], }), { status: 200, headers: { "Content-Type": "application/json" }, })); const { POST } = await import("../../src/app/api/models/test/route.js"); const req = new Request("http://localhost/api/models/test", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "voyage/voyage-3-large", kind: "embedding", }), }); const res = await POST(req); const body = await res.json(); expect(body.ok).toBe(true); expect(global.fetch).toHaveBeenCalledWith( expect.stringContaining("/api/v1/embeddings"), expect.objectContaining({ method: "POST", body: JSON.stringify({ model: "voyage/voyage-3-large", input: "test", }), }) ); }); it("fails embedding model tests when provider returns no embedding data", async () => { global.fetch = vi.fn().mockResolvedValue(new Response(JSON.stringify({ data: [{ embedding: null }], }), { status: 200, headers: { "Content-Type": "application/json" }, })); const { POST } = await import("../../src/app/api/models/test/route.js"); const req = new Request("http://localhost/api/models/test", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "voyage/voyage-3-large", kind: "embedding", }), }); const res = await POST(req); const body = await res.json(); expect(body.ok).toBe(false); expect(body.error).toBe("Provider returned no embedding data"); }); it("routes stt model tests to /api/v1/audio/transcriptions", async () => { global.fetch = vi.fn().mockResolvedValue(new Response(JSON.stringify({ text: "test", }), { status: 200, headers: { "Content-Type": "application/json" }, })); const { POST } = await import("../../src/app/api/models/test/route.js"); const req = new Request("http://localhost/api/models/test", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "hf/openai/whisper-small", kind: "stt", }), }); const res = await POST(req); const body = await res.json(); expect(body.ok).toBe(true); expect(global.fetch).toHaveBeenCalledWith( expect.stringContaining("/api/v1/audio/transcriptions"), expect.objectContaining({ method: "POST", body: expect.any(FormData), }) ); }); it("returns formatted HTTP errors for non-2xx embedding responses", async () => { global.fetch = vi.fn().mockResolvedValue(new Response(JSON.stringify({ error: { message: "bad upstream" }, }), { status: 502, headers: { "Content-Type": "application/json" }, })); const { POST } = await import("../../src/app/api/models/test/route.js"); const req = new Request("http://localhost/api/models/test", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "voyage/voyage-3-large", kind: "embedding", }), }); const res = await POST(req); const body = await res.json(); expect(body.ok).toBe(false); expect(body.status).toBe(502); expect(body.error).toBe("HTTP 502: bad upstream"); }); });