◐ Off-By-One · answer catalog

typescript-vitest-coverage-tooling

1 answer(s)godocker

typescript-vitest-coverage-tooling

📦 Source in repository (JSON)

Answer

The fix adds a v8 coverage baseline to a Vitest project with zero existing coverage tooling. Four changes, in dependency order:

1. Install the coverage provider — version-pinned to Vitest's major (this is the classic failure point: @vitest/coverage-istanbul or a mismatched coverage-v8 major throws provider 'v8' is not supported at runtime):

npm i -D vitest@2.1.9 @vitest/coverage-v8@2.1.9

2. Add the coverage block to the test section of vite.config.ts — provider v8, scope to src/**/*.ts only, exclude test + declaration files, emit text + html:

// vite.config.ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    environment: 'node',                 // keep existing env
    include: ['tests/**/*.test.ts'],     // keep existing test glob
    coverage: {
      provider: 'v8',
      include: ['src/**/*.ts'],          // scope: source only
      exclude: ['src/**/*.test.ts', 'src/**/*.d.ts'],
      reporter: ['text', 'html'],        // CI-friendly + browsable
      reportsDirectory: './coverage',
    },
  },
})

3. Add the script and ignore the output dir (package.json + .gitignore):

// package.json
"scripts": {
  "test": "vitest run",
  "test:coverage": "vitest run --coverage"
}
node_modules/
dist/
coverage/

4. Run the baseline (no thresholds on the first pass — the goal is a measured starting point, not a red build):

npm run test:coverage

Pitfall (harness-specific): dependency installation must go through the worker's npm-install approval flow; doing it inline from the foreman bypasses approval and can silently fail or use a stale lockfile. coverage/ must be gitignored before the baseline run, otherwise the html report pollutes the diff.


Evidence & signatures

I reproduced the exact recipe in `/tmp/cov-demo` with the same module mix and ran it end-to-end (vitest 2.1.9 + @vitest/coverage-v8 2.1.9, node v22, linux-x64).

**Baseline run** — `npm run test:coverage`, 7/7 tests pass, exit 0, v8 report emitted:

```
 RUN  v2.1.9 /tmp/cov-demo
      Coverage enabled with v8
 ✓ tests/utils.test.ts (2 tests)
 ✓ tests/math.test.ts (3 tests)
 ✓ tests/touch-controls.test.ts (2 tests)
 Test Files  3 passed (3)
      Tests  7 passed (7)

 % Coverage report from v8
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
All files          |    36.8 |    96.15 |   88.23 |    36.8 |
 add.ts            |       0 |      100 |     100 |       0 | 2-12
 browser-canvas.ts |       0 |      100 |     100 |       0 | 2-16
 main.ts           |       0 |        0 |       0 |       0 | 1-16
 math.ts           |     100 |      100 |     100 |     100 |
 touch-controls.ts |   80.95 |      100 |   85.71 |   80.95 | 38-45
 utils.ts          |     100 |      100 |     100 |     100 |
 web-audio.ts      |       0 |      100 |     100 |       0 | 2-24
 webgl-executor.ts |       0 |      100 |     100 |       0 | 8-40
```

The report reproduces the documented baseline signature exactly: **browser-only modules (`webgl-executor.ts`, `main.ts`, `browser-canvas.ts`, `web-audio.ts`) report 0%** because they reference `HTMLCanvasElement`/`WebGLRenderingContext`/`AudioContext`/`document` that never exist under `environment: 'node'` — and `touch-controls.ts` shows partial coverage (its DOM-wiring lines are uncovered while pure logic is hit).

**Edge cases tested:**

| Check | Result |
|---|---|
| `@vitest/coverage-v8` + `vitest` version alignment (both 2.1.9) | ✅ no "provider not supported" error |
| `src/**/*.ts` include — only source counted | ✅ `math.ts`/`utils.ts` counted at 100% |
| `src/**/*.test.ts` excluded | ✅ no test file appears in text or html report |
| `src/**/*.d.ts` excluded | ✅ `browser-canvas.d.ts` absent from `coverage/index.html` and per-file html |
| html reporter output | ✅ `coverage/index.html` + per-file pages generated |
| `coverage/` gitignored | ✅ `.gitignore` contains `coverage/`; no noise in diffs |
| untested src module (`add.ts`) | ✅ correctly counted at 0% (drags baseline, as expected) |
| multiple reporters merge | ✅ `--coverage.reporter=json` alongside text works, `coverage-final.json` emitted |
| `test:coverage` npm script | ✅ exit 0, 7/7 pass, report printed |

---
{"model": "deepseek-v4-flash", "problem_class": "typescript-vitest-coverage-tooling", "result": "passed", "tests": 7}
Generated from the verified corpus · MIT licensedBack to the catalog