test(middleware): pin NODE_ENV for the CSP assertions - #934
Conversation
applySecurityHeaders skips the CSP in development on purpose, so the security header assertions only hold outside it. They never said so: they inherited whatever the runner set, and passed only because vitest 4 overrode NODE_ENV to 'test' inside the test environment despite 'npm run test' passing NODE_ENV=development. vitest 5 does not override it. The value reaches the middleware as 'development', the CSP branch is skipped, and twelve assertions read a null header — the whole of the remaining failure on the vitest 5 bump. Stub the value in the block that depends on it, and add the test the dev exemption never had: in development there is no CSP, but the static headers are still set. That branch flipping is what went unnoticed. Verified on both: 2529 pass on vitest 4, and 31/31 in this file on vitest 5 with NODE_ENV=development.
There was a problem hiding this comment.
AI Automated Review
Full PR review.
Analysis engine: MiniMax-M2.7@https://litellm.jory.dev/v1 (anthropic) — primary route
PR PR 934: test(middleware): pin NODE_ENV for the CSP assertions
Recommendation
Approve. This is a focused, well-documented test fix that addresses flaky CSP header assertions caused by vitest 5 no longer overriding NODE_ENV to "test" inside the test environment. All CI checks pass.
Change-by-Change Findings
| File | Change | Assessment |
|---|---|---|
src/middleware.test.ts |
Pin NODE_ENV to "production" in beforeEach via vi.stubEnv |
Correct — explicitly states the environment condition the CSP assertions test against |
src/middleware.test.ts |
Add vi.unstubAllEnvs() in afterEach |
Correct — restores the environment after each test |
src/middleware.test.ts |
Add new test: "does not set a CSP in development, but still sets the static headers" | Good — provides coverage for the previously untested development exemption branch |
The new test asserts that in development mode: (1) content-security-policy is null, and (2) static headers (x-content-type-options, x-frame-options) are still set. This pins the exemption behavior in both directions.
Standards Compliance
The repository's AGENTS.md and codebase conventions were consulted. This PR:
- Uses
vi.stubEnv/vi.unstubAllEnvs— the canonical vitest pattern for environment variable isolation in tests - Cleans up after each test (
afterEach) - Adds explanatory comments inline rather than relying on external context
- Does not introduce any secrets, auth changes, or database modifications
- Single file modified:
src/middleware.test.ts
No repository standards are violated.
Tool Harness Findings
No tool harness output was provided in the corpus.
CI Check Results
All 11 CI checks passed for commit 80537d77:
| Check | Result |
|---|---|
| Tests | ✓ success |
| Typecheck | ✓ success |
| Lint | ✓ success |
| Coverage | ✓ success |
| Build | ✓ success |
| Docker Build | ✓ success |
| Docker Build (MCP) | ✓ success |
| npm audit | ✓ success |
| smoke | ✓ success |
| Database migrations | ✓ success |
| Database integration | ✓ success |
Unknowns / Needs Verification
None. The PR description provides verification evidence from both vitest 4 and vitest 5 runs, and all CI checks confirm the fix is correct.
Summary
This is a low-risk test-only change that fixes a legitimate test reliability issue introduced by the vitest 5 upgrade. The fix is minimal (24 lines added), well-explained, and verified by CI. No changes to production code.
Summary
security headersblock stubsNODE_ENVinstead of inheriting it from the runner.Second and final blocker on #929 (vitest 5). With #933 already merged, this makes it green.
Why
applySecurityHeadersskips the CSP in development on purpose — Next invokes the proxy several times per document request and the browser intersects the resulting CSP headers, collapsingscript-srcand breaking hydration.src/middleware.tsexplains it at length.The tests never stated that dependency. They read whatever
NODE_ENVthe runner provided, and passed only because vitest 4 overrode it totestinside the test environment — even thoughnpm run testrunsNODE_ENV=development vitest run.vitest 5 does not override it. The value reaches the middleware as
development, the CSP branch is skipped, and twelve assertions read a null header:So the assertions were correct and the setup was accidental. This makes the block state the condition it is testing.
The missing test
The development branch had no coverage at all, which is why nothing noticed when it silently became the branch under test. Added: in development there is no CSP, but the static headers are still set. That pins the exemption in both directions.
Verification
vitest/5.0.0installed and ran it withNODE_ENV=development— 31/31 pass, where it was 12 failed / 18 passed before.Note
Worth knowing separately:
npm run testsetsNODE_ENV=development, and under vitest 5 that now actually reaches the code under test. Any other test whose behaviour forks onNODE_ENVis in the same position — these were the only ones failing, but they were also the only ones with a fork.https://claude.ai/code/session_01YSuDvZq9ncvyX85Uzx3cQh