import { describe, it, expect, vi, beforeEach } from "vitest"; const findByID = vi.fn(); vi.mock("payload", () => ({ getPayload: vi.fn(async () => ({ findByID })), })); vi.mock("@repo/core-cms", () => ({ default: Promise.resolve({}) })); const validateSession = vi.fn(); vi.mock("@repo/auth/di/container", () => ({ authContainer: { get: () => ({ validateSession }) }, })); const consentFactory = vi.fn(async () => ({})); const dsrBinding = { marker: "dsr-binding" }; const resolveBindingMode = vi.fn<() => "production" | "dev-seed">( () => "production", ); vi.mock("./bind-production", () => ({ bindAll: vi.fn(async () => {}), getComplianceBindings: vi.fn(async () => ({ consentFactory, dsrBinding })), resolveBindingMode: () => resolveBindingMode(), })); import { createWebNextTrpcContext } from "./trpc-context"; function makeRequest(headers: Record = {}): Request { return new Request("https://example.test/api/trpc", { headers }); } describe("createWebNextTrpcContext (A11)", () => { beforeEach(() => { vi.clearAllMocks(); resolveBindingMode.mockReturnValue("production"); findByID.mockResolvedValue({ id: "user-1", role: "admin" }); validateSession.mockResolvedValue({ user: { id: "user-1" } }); }); it("threads compliance bindings for anonymous requests", async () => { const ctx = await createWebNextTrpcContext(makeRequest()); expect(ctx.user).toBeUndefined(); expect(ctx.userId).toBeUndefined(); expect(ctx.consentFactory).toBe(consentFactory); expect(ctx.dsrBinding).toBe(dsrBinding); expect(validateSession).not.toHaveBeenCalled(); }); it("derives clientIp from proxy headers (B2)", async () => { const ctx = await createWebNextTrpcContext( makeRequest({ "x-forwarded-for": "203.0.113.9" }), ); expect(ctx.clientIp).toBe("203.0.113.9"); }); it("resolves the user + role snapshot from the payload-token cookie", async () => { const ctx = await createWebNextTrpcContext( makeRequest({ cookie: "payload-token=jwt-abc; other=1" }), ); expect(validateSession).toHaveBeenCalledWith("jwt-abc"); expect(ctx.user).toEqual({ id: "user-1", roles: ["admin"] }); expect(ctx.userId).toBe("user-1"); }); it("resolves the dev-seed session cookie name too", async () => { resolveBindingMode.mockReturnValue("dev-seed"); const ctx = await createWebNextTrpcContext( makeRequest({ cookie: "session=session_user-1" }), ); expect(validateSession).toHaveBeenCalledWith("session_user-1"); // dev-seed has no Payload — role snapshot is empty expect(ctx.user).toEqual({ id: "user-1", roles: [] }); expect(findByID).not.toHaveBeenCalled(); }); it("treats an invalid/expired session as anonymous", async () => { validateSession.mockRejectedValue(new Error("Invalid or expired")); const ctx = await createWebNextTrpcContext( makeRequest({ cookie: "payload-token=tampered" }), ); expect(ctx.user).toBeUndefined(); }); it("yields no roles when the users doc has none", async () => { findByID.mockResolvedValue({ id: "user-1" }); const ctx = await createWebNextTrpcContext( makeRequest({ cookie: "payload-token=jwt-abc" }), ); expect(ctx.user).toEqual({ id: "user-1", roles: [] }); }); });