import { describe, it, expect, vi, afterEach } from "vitest"; vi.mock("server-only", () => ({})); const { cookieStore } = vi.hoisted(() => ({ cookieStore: { get: vi.fn(), }, })); vi.mock("next/headers", () => ({ cookies: vi.fn().mockResolvedValue(cookieStore), })); const makeHeaders = (values: Record) => ({ get: (key: string) => values[key.toLowerCase()] ?? values[key] ?? null, }); describe("GET /api/usage route", () => { const originalEnv = process.env; afterEach(() => { process.env = originalEnv; vi.unstubAllGlobals(); vi.clearAllMocks(); cookieStore.get.mockReturnValue(undefined); }); it("returns 200 with fallback payload when all upstreams fail", async () => { process.env = { ...originalEnv, MANAGEMENT_API_KEY: "test-key", USAGE_BACKEND_BASE_URL: "http://primary.local" }; cookieStore.get.mockReturnValue(undefined); vi.stubGlobal("fetch", vi.fn().mockRejectedValue(new Error("connect ECONNREFUSED"))); const { GET } = await import("@/app/api/usage/route"); const res = await GET(new Request("http://localhost/api/usage")); expect(res.status).toBe(200); const body = await res.json(); expect(body.error).toBe("upstream_unreachable"); expect(body.usage).toBeTruthy(); expect(body.failed_requests).toBe(0); }); it("passes through successful upstream JSON", async () => { process.env = { ...originalEnv, MANAGEMENT_API_KEY: "test-key", USAGE_BACKEND_BASE_URL: "http://primary.local" }; cookieStore.get.mockReturnValue(undefined); vi.stubGlobal( "fetch", vi.fn().mockResolvedValue({ ok: true, headers: makeHeaders({ "content-type": "application/json" }), json: async () => ({ usage: { total_requests: 1, success_count: 1, failure_count: 0, total_tokens: 10, apis: {}, requests_by_day: {}, requests_by_hour: {}, tokens_by_day: {}, tokens_by_hour: {}, }, failed_requests: 0, }), }) ); const { GET } = await import("@/app/api/usage/route"); const res = await GET(new Request("http://localhost/api/usage")); expect(res.status).toBe(200); const body = await res.json(); expect(body.failed_requests).toBe(0); expect(body.usage.total_requests).toBe(1); }); it("aggregates usage from primary and extra sources", async () => { process.env = { ...originalEnv, MANAGEMENT_API_KEY: "test-key", USAGE_BACKEND_BASE_URL: "http://primary.local" }; cookieStore.get.mockReturnValue({ value: encodeURIComponent(JSON.stringify(["http://secondary.local"])), }); const fetchMock = vi.fn(async (url: string | URL) => { const asString = String(url); if (asString.includes("primary.local")) { return { ok: true, headers: makeHeaders({ "content-type": "application/json" }), json: async () => ({ usage: { total_requests: 2, success_count: 2, failure_count: 0, total_tokens: 100, apis: { primary: { total_requests: 2, total_tokens: 100, models: { "gpt-4-turbo": { total_requests: 2, total_tokens: 100, details: [], }, }, }, }, requests_by_day: { "2026-02-12": 2 }, requests_by_hour: { "12": 2 }, tokens_by_day: { "2026-02-12": 100 }, tokens_by_hour: { "12": 100 }, }, failed_requests: 0, }), }; } return { ok: true, headers: makeHeaders({ "content-type": "application/json" }), json: async () => ({ usage: { total_requests: 3, success_count: 2, failure_count: 1, total_tokens: 150, apis: { secondary: { total_requests: 3, total_tokens: 150, models: { "gpt-4-turbo": { total_requests: 3, total_tokens: 150, details: [], }, }, }, }, requests_by_day: { "2026-02-12": 3 }, requests_by_hour: { "12": 3 }, tokens_by_day: { "2026-02-12": 150 }, tokens_by_hour: { "12": 150 }, }, failed_requests: 1, }), }; }); vi.stubGlobal("fetch", fetchMock); const { GET } = await import("@/app/api/usage/route"); const res = await GET(new Request("http://localhost/api/usage")); expect(res.status).toBe(200); const body = await res.json(); expect(body.usage.total_requests).toBe(5); expect(body.usage.success_count).toBe(4); expect(body.usage.failure_count).toBe(1); expect(body.usage.total_tokens).toBe(250); expect(body.failed_requests).toBe(1); expect(body.usage.requests_by_day["2026-02-12"]).toBe(5); expect(body.usage.tokens_by_hour["12"]).toBe(250); expect(body.usage.apis.primary.total_requests).toBe(2); expect(body.usage.apis.secondary.total_requests).toBe(3); }); });