// @vitest-environment node
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
const { listGateModels, updateLastModelId } = vi.hoisted(() => ({
listGateModels: vi.fn(),
updateLastModelId: vi.fn(),
}));
vi.mock("server-only", () => ({}));
vi.mock("@/lib/chat/catalog", () => ({ listGateModels }));
vi.mock("@/lib/db/pool", () => ({ getPool: () => ({}) }));
vi.mock("@/lib/db/users", () => ({ updateLastModelId }));
import { PATCH } from "@/app/api/me/model/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");
listGateModels.mockReset();
updateLastModelId.mockReset();
});
afterEach(() => vi.unstubAllEnvs());
describe("PATCH /api/me/model", () => {
it("persists an arbitrary valid model only after catalog confirmation", async () => {
listGateModels.mockResolvedValue([
{ id: "auto", name: "Aegida Auto", description: "Auto" },
{ id: "claude-sonnet.4", name: "Claude", description: "Claude" },
]);
const response = await PATCH(await requestFor("claude-sonnet.4"));
expect(response.status).toBe(200);
expect(await response.json()).toEqual({ model: "claude-sonnet.4" });
expect(updateLastModelId).toHaveBeenCalledWith(
expect.anything(),
"11111111-1111-4111-8111-111111111111",
"claude-sonnet.4",
);
});
it("rejects a valid slug that is absent from the authenticated catalog", async () => {
listGateModels.mockResolvedValue([
{ id: "auto", name: "Aegida Auto", description: "Auto" },
]);
const response = await PATCH(await requestFor("removed-model"));
expect(response.status).toBe(400);
expect(updateLastModelId).not.toHaveBeenCalled();
});
});
async function requestFor(model: string): Promise<Request> {
const token = await signAuthToken({
id: "11111111-1111-4111-8111-111111111111",
email: "user@example.corp",
externalUserId: "42",
});
return new Request("http://localhost/api/me/model", {
method: "PATCH",
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
body: JSON.stringify({ model }),
});
}