import { describe, it, expect, vi, beforeEach } from "vitest"; const responseMock = vi.hoisted(() => { function makeResponseMock() { const store = new Map(); return { _store: store, headers: { set: vi.fn((k: string, v: string) => store.set(k, v)), get: vi.fn((k: string) => store.get(k) ?? null), }, }; } return { makeResponseMock }; }); vi.mock("next/server", () => ({ NextResponse: { next: vi.fn(), }, })); import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; import { middleware } from "../middleware"; const ALL_SIX_HEADERS = [ "Strict-Transport-Security", "X-Frame-Options", "X-Content-Type-Options", "Referrer-Policy", "Permissions-Policy", "Content-Security-Policy", ] as const; function makeRequest(): NextRequest { return { headers: new Headers() } as unknown as NextRequest; } describe("cms middleware", () => { let mock: ReturnType; beforeEach(() => { mock = responseMock.makeResponseMock(); vi.mocked(NextResponse.next).mockReturnValue( mock as unknown as ReturnType, ); }); it("sets all six security headers on the response", () => { middleware(makeRequest()); for (const header of ALL_SIX_HEADERS) { expect(mock._store.has(header)).toBe(true); } }); it("does not set a nonce header", () => { middleware(makeRequest()); expect(mock._store.has("x-nonce")).toBe(false); }); it("CSP is permissive in development mode", () => { vi.stubEnv("NODE_ENV", "development"); middleware(makeRequest()); const csp = mock._store.get("Content-Security-Policy"); expect(csp).toContain("'unsafe-inline'"); }); it("CSP uses strict-dynamic in production mode", () => { vi.stubEnv("NODE_ENV", "production"); middleware(makeRequest()); const csp = mock._store.get("Content-Security-Policy"); expect(csp).toContain("'strict-dynamic'"); }); });