Appearance
date: 2026-06-06 tags: [testing, vitest, coverage, v8, frontend] status: active graduated_to:
vi.stubGlobal('window', …) zeroes v8 coverage for the file under test
Symptom — A fully-tested module reported no v8 coverage: resources/js/lib/markdown.ts never appeared in the report (even with coverage.all: true + an explicit coverage.include), so a per-file threshold couldn't gate it.
Root cause — One of its tests calls vi.stubGlobal('window', undefined) to hit the SSR-escape branch (typeof window === 'undefined'). That clobbers the global v8's coverage collector relies on, so v8 drops attribution for the whole module. Proven: with the SSR test present markdown.ts is absent from coverage; remove that one test and the same file measures 71%.
Fix — Don't stub window at all to reach a no-DOM branch — run that test in the node environment, where window is genuinely absent, so v8's attribution stays intact. Issue #318 split the SSR-escape branch into its own file, resources/js/lib/markdown.ssr.test.ts, headed by a // @vitest-environment node directive (the rest of markdown.test.ts stays jsdom); with the stubGlobal gone, markdown.ts was re-added to the per-file gate. The interim (Sprint #252) had simply omitted the file from the gate.
Guard — markdown.ts is back in vitest.config.ts coverage.include (vitest.config.ts:27) under the per-file floor; markdown.ssr.test.ts:1 pins the node environment with a comment pointing here. The general rule: reach a no-DOM branch via // @vitest-environment node, never vi.stubGlobal('window', undefined), in any file whose coverage you gate.