Files
confidence-engine/tests/auth-boundary.test.js
T

80 lines
2.9 KiB
JavaScript

import { beforeEach, describe, expect, it, vi } from "vitest";
import { NextRequest } from "next/server";
const mockGetAuthenticatedUser = vi.fn();
const mockStartCase = vi.fn();
const mockGetUser = vi.fn();
const mockGetConfig = vi.fn();
vi.mock("@/lib/supabase/server.js", () => ({
getAuthenticatedUser: () => mockGetAuthenticatedUser(),
}));
vi.mock("@/lib/graph/orchestrator.js", () => ({
startCase: (...args) => mockStartCase(...args),
}));
vi.mock("@/lib/config", () => ({
getConfig: () => mockGetConfig(),
}));
vi.mock("@supabase/ssr", () => ({
createServerClient: () => ({ auth: { getUser: () => mockGetUser() } }),
}));
describe("authenticated product boundary", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("rejects an unauthenticated protected API request", async () => {
mockGetAuthenticatedUser.mockResolvedValue(null);
const { withAuthenticatedApi } = await import("@/lib/supabase/api-auth.js");
const handler = vi.fn();
const response = await withAuthenticatedApi(handler)(new Request("http://localhost/api/cases/start"));
expect(response.status).toBe(401);
expect(handler).not.toHaveBeenCalled();
});
it("allows an authenticated protected API request to reach existing route behavior", async () => {
mockGetAuthenticatedUser.mockResolvedValue({ id: "user-1" });
mockStartCase.mockResolvedValue({ success: true, updatedSituationGraph: {} });
const { POST } = await import("@/app/api/cases/start/route.js");
const response = await POST(new Request("http://localhost/api/cases/start", {
method: "POST",
body: JSON.stringify({ scenario: "A scenario" }),
}));
expect(response.status).toBe(200);
await expect(response.json()).resolves.toMatchObject({ success: true });
expect(mockStartCase).toHaveBeenCalledWith({ scenario: "A scenario" });
});
it("supplies the auth callback as the magic-link redirect target", async () => {
const { magicLinkRedirectTo } = await import("@/lib/supabase/browser.js");
expect(magicLinkRedirectTo("http://localhost:3000")).toBe("http://localhost:3000/auth/callback");
});
it("keeps infrastructure health public", async () => {
mockGetConfig.mockReturnValue({ ok: false });
const { GET } = await import("@/app/api/health/route.js");
const response = await GET();
expect(response.status).toBe(500);
await expect(response.json()).resolves.toMatchObject({ configPresent: false });
expect(mockGetAuthenticatedUser).not.toHaveBeenCalled();
});
it("redirects unauthenticated product access to the login surface", async () => {
mockGetUser.mockResolvedValue({ data: { user: null } });
const { middleware } = await import("@/middleware.js");
const response = await middleware(new NextRequest("http://localhost:3000/"));
expect(response.status).toBe(307);
expect(response.headers.get("location")).toBe("http://localhost:3000/login?next=%2F");
});
});