From 4dc58395c0b8bc0dffc613ebca34d939d93edba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 24 Sep 2026 12:52:42 +0000 Subject: [PATCH] :recycle: Run doc tests outside the coverage gate An example that exercises a line no hand-written test reaches would let the `--100` gate pass on documentation alone. Node has no file-level exclusion, and c8's `--exclude` only filters the report, so run the two in separate processes: `test:coverage` runs c8 over the tracked tests only (`git ls-files`, which skips the untracked generated files), and `test:doc` runs the generated examples without c8. `test:ci` chains them. --- CONTRIBUTING.md | 5 +++-- development/docs.md | 6 ++++++ package.json | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9d27b5a..0e07828 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -140,8 +140,9 @@ CI step. Pick the prefix that matches the script's lifecycle: `npm run fix`; the diff is the review surface. - `test:*` — test scripts. `test` is the canonical entry point (`check:tsc` + unit tests); `test:unit` skips the typecheck for fast local iteration; - `test:ci` runs the suite under c8 and fails below 100% coverage on `src/` - (CI-only; `verify` stays coverage-free). + `test:coverage` runs c8 over the hand-written tests only; `test:doc` runs the + generated doc examples without coverage; `test:ci` chains the two and fails + below 100% coverage on `src/` (CI-only; `verify` stays coverage-free). - `watch:*` — long-running watchers for the manual inner dev loop. Aggregated by `watch`. - `maintain:*` — advisory repo-maintenance scans: read-only, but whole-project diff --git a/development/docs.md b/development/docs.md index d93aa0d..4a22084 100644 --- a/development/docs.md +++ b/development/docs.md @@ -49,3 +49,9 @@ Compile every `ts / `typescript fence in the prose docs into a real out of the `--100` gate. Do not add an `--exclude` for them: passing any `--exclude` replaces the defaults, so every hand-written test file and `__tests__/` helper re-enters coverage and the gate fails. +- Generated examples must not run under `c8`: an example could cover a line no + hand-written test reaches, so the coverage gate would pass on documentation + alone. `test:coverage` therefore runs c8 over the tracked tests only + (`git ls-files 'src/*.test.ts'` — the generated files are untracked), and + `test:doc` runs the examples in a separate process without c8. `test:ci` + chains the two, so correctness and coverage stay independent. diff --git a/package.json b/package.json index 846d380..e9facd1 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,9 @@ "maintain:outdated": "check-outdated --ignore-pre-releases --ignore-packages @types/node", "test": "npm run check:tsc && node --test --strip-types \"src/**/*.test.ts\"", "pretest:ci": "npm run create:doc-tests", - "test:ci": "c8 --all --include \"src/**/*.ts\" --reporter=text --reporter=lcov --reporter=html --100 node --test --strip-types \"src/**/*.test.ts\"", + "test:ci": "npm run test:coverage && npm run test:doc", + "test:coverage": "c8 --all --include \"src/**/*.ts\" --reporter=text --reporter=lcov --reporter=html --100 node --test --strip-types $(git ls-files 'src/*.test.ts')", + "test:doc": "node --test --strip-types \"src/doc-test/__generated__/*.test.ts\"", "test:unit": "node --test --strip-types \"src/**/*.test.ts\"", "verify": "npm run check && npm run test:unit", "watch": "npm run watch:test",