import { beforeEach, describe, expect, it, vi } from "vitest"; /** * Every API handler must refuse a signed-out request before doing anything else * (vrek iss-76d5wrb). The camera and store modules are replaced with spies that must never * be reached. */ const denied = vi.fn<() => Promise>(); vi.mock("@/lib/access", () => ({ apiAccessDenied: denied })); const touched = vi.fn(); const trap = () => touched(); vi.mock("@/lib/camera", () => ({ getCameraInfo: trap, getSnapshot: trap, testCredentials: trap, resetConnection: trap, })); vi.mock("@/lib/camera-route", () => ({ cameraTarget: trap, cameraErrorResponse: trap })); vi.mock("@/lib/credential-store", () => ({ credentialsSchema: { safeParse: trap }, setCredentials: trap, deleteCredentials: trap, describeCredentials: trap, })); vi.mock("@/lib/onvif", () => ({ discoverCameras: trap, discoverRequestSchema: { safeParse: trap } })); vi.mock("@/lib/camera-registry", () => ({ recordDiscovered: trap })); const info = await import("./cameras/[id]/info/route"); const snapshot = await import("./cameras/[id]/snapshot/route"); const credentials = await import("./cameras/[id]/credentials/route"); const discover = await import("./discover/route"); const ctx = { params: Promise.resolve({ id: "11111111-2222-3333-4444-555555555555" }) }; const req = (method = "GET") => new Request("http://localhost/api/x", { method, body: method === "GET" ? undefined : "{}" }); const handlers: [string, () => Promise][] = [ ["GET /api/cameras/[id]/info", () => info.GET(req(), ctx)], ["GET /api/cameras/[id]/snapshot", () => snapshot.GET(req(), ctx)], ["GET /api/cameras/[id]/credentials", () => credentials.GET(req(), ctx)], ["PUT /api/cameras/[id]/credentials", () => credentials.PUT(req("PUT"), ctx)], ["DELETE /api/cameras/[id]/credentials", () => credentials.DELETE(req("DELETE"), ctx)], ["POST /api/discover", () => discover.POST(req("POST"))], ]; describe("API access control", () => { beforeEach(() => { touched.mockReset(); denied.mockReset().mockResolvedValue(Response.json({ error: "Sign in required" }, { status: 401 })); }); it.each(handlers)("%s returns 401 and touches nothing when signed out", async (_name, call) => { const res = await call(); expect(res.status).toBe(401); expect(await res.json()).toEqual({ error: "Sign in required" }); expect(touched).not.toHaveBeenCalled(); }); });