Shinwayy / frontend /tests /api-usage.route.test.ts
Shinway Deploy
track binary files with git-lfs
db492de
Raw
History Blame Contribute Delete
5.42 kB
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<string, string>) => ({
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);
});
});