// @vitest-environment node
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("server-only", () => ({}));
import { GET } from "@/app/api/models/route";
import { signAuthToken } from "@/lib/auth/server";
beforeEach(() => {
vi.stubEnv("JWT_SECRET", "ai-control-center-local-development-secret-2026");
vi.stubEnv("JWT_ISSUER", "corp-ui");
vi.stubEnv("JWT_AUDIENCE", "aegida-gate");
vi.stubEnv("AEGIDA_TENANT_ID", "tenant-1");
vi.stubEnv("AEGIDA_GATE_URL", "https://gate.example.test");
});
afterEach(() => {
vi.unstubAllEnvs();
vi.unstubAllGlobals();
});
describe("GET /api/models", () => {
it("authenticates and returns a safe dynamic model catalog", async () => {
const fetchMock = vi.fn().mockResolvedValue(
Response.json({
object: "list",
data: [
{ id: "auto", object: "model", created: 1_785_758_400, owned_by: "aegida" },
{ id: "qwen", object: "model", created: 1_785_758_400, owned_by: "qwen" },
],
}),
);
vi.stubGlobal("fetch", fetchMock);
const authorization = `Bearer ${await userToken()}`;
const response = await GET(
new Request("http://localhost/api/models", { headers: { Authorization: authorization } }),
);
expect(response.status).toBe(200);
expect(response.headers.get("Cache-Control")).toBe("no-store");
expect(await response.json()).toEqual({
models: [
{
id: "auto",
name: "Aegida Auto",
description: "Автоматический выбор модели через Aegida Gate.",
},
{ id: "qwen", name: "Qwen", description: "Владелец модели: qwen." },
],
});
expect((fetchMock.mock.calls[0]?.[1] as RequestInit).headers).toEqual({
Accept: "application/json",
Authorization: authorization,
});
});
it("keeps auth failures as 401 and sanitizes every other upstream failure", async () => {
const authorization = `Bearer ${await userToken()}`;
vi.stubGlobal(
"fetch",
vi
.fn()
.mockResolvedValueOnce(new Response("private-auth-sentinel", { status: 401 }))
.mockResolvedValueOnce(new Response("private-upstream-sentinel", { status: 500 })),
);
const unauthorized = await GET(
new Request("http://localhost/api/models", { headers: { Authorization: authorization } }),
);
expect(unauthorized.status).toBe(401);
expect(JSON.stringify(await unauthorized.json())).not.toContain("private-auth-sentinel");
const unavailable = await GET(
new Request("http://localhost/api/models", { headers: { Authorization: authorization } }),
);
expect(unavailable.status).toBe(503);
expect(JSON.stringify(await unavailable.json())).not.toContain("private-upstream-sentinel");
});
it("rejects a missing user token before contacting Gate", async () => {
const fetchMock = vi.fn();
vi.stubGlobal("fetch", fetchMock);
const response = await GET(new Request("http://localhost/api/models"));
expect(response.status).toBe(401);
expect(fetchMock).not.toHaveBeenCalled();
});
});
async function userToken(): Promise<string> {
return signAuthToken({
id: "11111111-1111-4111-8111-111111111111",
email: "user@example.corp",
externalUserId: "42",
});
}