Files
agentic-dev/apps/cms/src/middleware.test.ts
2026-07-12 08:15:46 +00:00

82 lines
2.0 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from "vitest";
const responseMock = vi.hoisted(() => {
function makeResponseMock() {
const store = new Map<string, string>();
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<typeof responseMock.makeResponseMock>;
beforeEach(() => {
mock = responseMock.makeResponseMock();
vi.mocked(NextResponse.next).mockReturnValue(
mock as unknown as ReturnType<typeof NextResponse.next>,
);
});
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'");
});
});