Testing
The test trinity
Section titled “The test trinity”Three vitest harnesses + one perf harness. Coverage from all of them feeds into a merged report (PRD R6).
| Harness | Config | Includes | Cadence |
|---|---|---|---|
| Unit | vitest.config.ts |
src/**/__tests__/*.test.ts, tests/unit/**/*.test.ts, tests/integration/**/*.test.ts |
every PR (pnpm test) |
| Browser FREE | vitest.browser.free.config.ts |
tests/browser/{free-visual,simple-rpg-visual,react-bindings}.test.ts, tests/browser/feature-gallery.spec.ts, harness smoke |
required merged coverage job on every PR; full screenshot command is local proof |
| Browser EXTRA | vitest.browser.extra.config.ts |
tests/browser/extra-visual.test.ts |
local-only with HEX_WORLDS_ENABLE_EXTRA=1 |
| E2E local-assets | vitest.browser.local-assets.config.ts |
tests/e2e/local-assets/**/*.test.ts |
local-only with HEX_WORLDS_ENABLE_LOCAL_ASSETS=1 |
| SimpleRPG e2e (GitHub) | vitest.simple-rpg-e2e.config.ts |
tests/e2e/simple-rpg-ci.test.ts |
scheduled CI with HEX_WORLDS_E2E_GITHUB=1 |
| SimpleRPG e2e (local) | vitest.simple-rpg-e2e.config.ts |
tests/e2e/simple-rpg-local-extra.test.ts |
local with HEX_WORLDS_LOCAL_REFERENCES=1 |
| Perf bench | n/a — direct vitest bench | tests/perf/*.bench.ts |
local-only, non-blocking |
Coverage gates
Section titled “Coverage gates”vitest.coverage.shared.ts exports COVERAGE_THRESHOLDS at the current floor. PRD A8 ratchets these toward 100/100/100/100 via Epic E0-E10; each commit that closes a coverage gap raises the floor in the same commit.
CI’s required Coverage job bootstraps FREE models, collects unit coverage, collects browser-free coverage, then runs pnpm coverage:merge:enforce; regressions block merge.
To merge harness reports locally:
HEX_WORLDS_COVERAGE=1 pnpm coverage:allopen coverage/merged/lcov-report/index.htmlSimpleRPG: the coverage driver
Section titled “SimpleRPG: the coverage driver”tests/integration/simple-rpg/simple-rpg.ts is a 1,005-line driver that exercises 80+ public APIs synchronously. Its purpose isn’t gameplay — it’s coverage. Read the SimpleRPG README for the API matrix.
Three entry-point functions matter:
runSimpleRpgUsageExample()— full scenario → simulation → snapshot path; returns aSimpleRpgUsageSummarywith every metric the coverage ledger needs.summarizeSimpleRpgGuidePublicApiExercises()— pure-data coverage map; safe to call repeatedly (no koota worlds).runSimpleRpgExecutableGuideApiSmoke()— executable smoke of every guide-page helper API.
The CLI’s coverage subcommand consumes these to emit docs/release-readiness.json + Markdown ledgers.
Perf benches
Section titled “Perf benches”tests/perf/warm-start.bench.ts (PRD A3b) tracks the cost of blueprint → board → koota runtime → facade snapshot. Run:
pnpm bench:warm-startBaseline as of 2026-05-26: ~27 Hz / 37 ms mean.
Add more benches to tests/perf/ as PRD B/D-series perf work lands. The bench harness is opt-in (not in default pnpm test).
Visual regression
Section titled “Visual regression”tests/browser/__screenshots__/ holds committed PNG snapshots that vitest-browser compares against every render. Drift fails the build until either the diff is accepted (new snapshot committed) or fixed.
The screenshot assertion script is tests/scripts/assert-screenshots.ts; local visual commands call it via pnpm test:screenshots:free + :extra + :local-assets.
What CI actually runs
Section titled “What CI actually runs”See .github/workflows/ci.yml. The chain (post-PRD A9 install-once):
installjob —pnpm install --frozen-lockfileonce, uploadsnode_modules.tar.zstartifact.checkmatrix —lint,typecheck,build,test(each downloads + restores the artifact).coverage— bootstraps FREE models, collects unit + browser-free coverage, then enforces the merged ratchet.docs-site— Astro Starlight build with generated CLI reference.dependency-review— fail-on-severity: high.semgrep— OWASP Top 10 + Node.js SAST.
Local proof uses pnpm verify for the fast source gates and pnpm coverage:all:enforce for the CI-shaped merged coverage gate.