Files
Codeman/.changeset/test-script-split.md
T
Codeman maintainer 947ff6f6fa chore(test): make npm test the CI gate and give each excluded suite a runner
`npm test` ran config/vitest.config.ts, which includes the browser, visual and
perf suites. On any machine without chromium, a free port and per-machine PNG
baselines that fails ~87 tests on a clean master, so the repo's most obvious
command could not be used as a pass/fail signal. The workaround had spread into
four docs as "never run bare `npm test`" warnings.

`npm test` now runs config/vitest.ci.config.ts — byte-for-byte what CI runs — so
local green means CI green. Verified: 264 files, 5248 tests, exit 0.

The suites it leaves out are not abandoned; each has a command:

  test:browser  5 Playwright files (chromium + a live server; codex-predictive-echo
                also needs a real codex binary)
  test:mobile   unchanged — the above plus per-machine PNG baselines
  test:perf     2 wall-clock benchmarks; need an otherwise idle machine
  test:all      the old everything-behaviour, kept reachable

test:ci is untouched (CI still calls it). test:watch and test:coverage follow
test onto the gate's config.

The more important half is the hole this closes. The exclusion list lived as
literals in one config and pointed one way only: a file excluded from CI and
added to no runner would be tested by NOTHING, silently, with every command
still green — vitest counts "no files matched a filter" as success. That is the
same shape as the #279/#280 blind spot already documented in CLAUDE.md.

So the globs moved to config/test-suites.ts, one array per REASON a suite cannot
run in CI, and all three configs derive from it. test/test-suite-partition.test.ts
then checks the arithmetic against the files on disk: it fails if any test file
is reachable by no runner, or by two. Confirmed it fires by orphaning a file and
watching it name it. The partition is exact today:

  gate 264 + browser 5 + perf 2 + mobile 9 = 280 = every *.test.ts in the repo

⚠️ One sharp edge, deliberate and documented: a file filter must match its
runner. `npm test -- test/mobile/keyboard.test.ts` now matches nothing and exits
GREEN having run zero tests, because the gate's config excludes that path.
CLAUDE.md recommended exactly that command in the on-screen-keyboard note; that
line now says `npm run test:mobile -- <file>`, and the Testing section calls out
the trap, since a green run of zero tests is worse than a red one.

Docs synced: CLAUDE.md, AGENTS.md, .github/CONTRIBUTING.md, README.md,
README.zh-CN.md, and two ci.yml comments that claimed only test/mobile/** was
excluded — it is three suites, and 5 Playwright files rather than 3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 19:55:23 +02:00

1.8 KiB

aicodeman
aicodeman
patch

npm test is now the CI gate and is safe to run bare; the suites it cannot run each got their own command.

npm test ran the everything-config, which fails ~87 tests on a clean master on any machine without chromium, a free port and per-machine PNG baselines. That made the repo's most obvious command useless as a pass/fail signal, and the docs had accumulated "never run bare npm test" warnings in four files to work around it. It now runs config/vitest.ci.config.ts — exactly what CI runs — so local green means CI green.

  • New: test:browser (5 Playwright files), test:perf (2 wall-clock benchmarks), test:all (the old everything-behaviour, kept reachable). test:ci and test:mobile are unchanged; test:watch and test:coverage follow test onto the gate's config.
  • The exclusion list moved to config/test-suites.ts, with the reason each suite cannot run in CI. Every config derives from it, so the gate's excludes and the runners' includes cannot drift.
  • That drift was a silent hole, not a tidiness problem: a file excluded from CI and added to no runner is tested by NOTHING, and every command stays green, because vitest counts "no files matched" as success. test/test-suite-partition.test.ts now fails if any test file is reachable by no runner or by two.
  • ⚠️ A file filter must match its runner: npm test -- test/mobile/keyboard.test.ts matches nothing and exits green having run zero tests, because the gate excludes that path. Use npm run test:mobile -- <file>. Documented in CLAUDE.md, and the one place that recommended the old form was corrected.
  • Docs synced: CLAUDE.md, AGENTS.md, .github/CONTRIBUTING.md, both READMEs, and two ci.yml comments that claimed only test/mobile/** was excluded (it is three suites, and 5 Playwright files rather than 3).