Tests + measured Node coverage
Verify behavior before shipping.
Run 156 unique contracts in four focused sets, enforce per-file coverage, smoke-test the packed artifact, and keep published badge evidence synchronized.
Verification commands
Use the smallest command that answers the question.
| Command | Use it for | Expected result |
|---|---|---|
npm test | Complete behavior check. | Runs every file discovered by the shared manifest; 156 unique leaf cases total. Ubuntu reports 155 pass + 1 Windows-only skip; Windows reports 156 pass. |
npm run test:unit | Config and suite discovery in isolation. | Runs the 34 cases under test/unit/. |
npm run test:functional | Normal public server behavior. | Runs the 46 cases under test/functional/. |
npm run test:integration | Module, CLI, benchmark, listener, stream, and filesystem boundaries. | Runs the 24 cases under test/integration/. |
npm run test:regression | Previously fixed failures and security boundaries. | Runs the 52 cases under test/regression/. |
npm run benchmark:smoke | Short real-server measurement. | Runs five validated public paths with 8 measured requests, 2 warmups, and 2 concurrent clients per scenario. |
npm run benchmark | Bounded developer measurement. | Runs the same five paths with 250 measured requests, 25 warmups, and 10 concurrent clients per scenario. |
npm run test:site | Static documentation contract. | Checks every page, local link/fragment, unique ID, label/ARIA target, image alt, current nav state, CSS delimiters, and site JavaScript syntax with Node built-ins only. |
npm run coverage | Coverage and badge evidence. | vanilla-test coverage node runs the suite, gates coverage, writes coverage/node/, then refreshes badge JSON. |
npm run test:package | Published-package contract. | Packs to an OS temporary directory, installs the tarball in an isolated consumer, verifies package contents, imports CommonJS/ESM/subpaths, runs the CLI, then cleans up. |
npm run verify | Full local release check. | Runs tests, static-doc checks, coverage, and package smoke in sequence. Tests run twice because coverage executes the suite again. |
npm ci
npm run verifyvanilla-test@2.1.1 release is the sole direct development dependency and native V8 coverage tool.Current suite
156 unique, focused cases in four sets.
Each of the 156 cases owns one focused behavior contract within a selectable engineering set.
| Set | Source | Cases | Primary contract | Run alone |
|---|---|---|---|---|
| Unit | test/unit/ | 34 | Config defaults, merging, isolation, validation, logger error handling, and suite discovery. | npm run test:unit |
| Functional | test/functional/ | 46 | Normal lifecycle, static HTTP, ranges, caching, compression, bodies, hooks, timeouts, logging, and deliberate dotfile opt-in. | npm run test:functional |
| Integration | test/integration/ | 24 | 14 module/CLI contracts, 3 benchmark harness contracts, and 7 listener, socket, stream, and filesystem boundary contracts. | npm run test:integration |
| Regression | test/regression/ | 52 | Previously fixed validation, lifecycle, range, path-security, hook, stream, filesystem, and logging failures. | npm run test:regression |
| Total | test/{unit,functional,integration,regression}/ | 156 | Unique leaf cases; Regression owns 52 fixed failure and security contracts. | npm test |
Source inventory
| Source file | Cases | Ownership |
|---|---|---|
test/unit/config-defaults.test.js | 8 | Loopback, static-file, MIME, server, error-header, domain, and MIME opt-out defaults. |
test/unit/config-isolation.test.js | 7 | Snapshot, nested value, settings, MIME, error-header, and domain isolation. |
test/unit/config-logging.test.js | 3 | Serialization plus asynchronous and synchronous filesystem logger failures. |
test/unit/config-merge.test.js | 4 | Restoring MIME, server, error, and error-header defaults after disabled maps. |
test/unit/config-validation.test.js | 9 | Record validation, prototype-key rejection, pollution safety, and null-prototype maps. |
test/unit/suites.test.js | 3 | Category inventory, unique file discovery, and unknown/repeated category rejection. |
test/functional/server.test.js | 46 | Public server behavior under normal supported inputs. |
test/integration/benchmark.test.js | 3 | Five-scenario smoke execution, finite ordered metrics, and benchmark CLI validation. |
test/integration/cli-arguments.test.js | 5 | CLI help, version, and invalid input. |
test/integration/cli-serving.test.js | 3 | Live CLI root serving and dotfile policy. |
test/integration/exports.test.js | 6 | CommonJS, ESM, Config, and MIME export identity. |
test/integration/server.test.js | 7 | Listener isolation, HTTPS wiring, binary/socket/SPA streams, abort cleanup, and NDJSON logging. |
test/regression/server.test.js | 52 | Permanent guards for fixed failure modes and security boundaries. |
| Total | 156 | One authoritative owner per behavior. |
test-results.json is the authoritative ordered evidence. It records status, counts, and every unique leaf description in the runner's execution order.Executable measurements
Run the real public-path harness.
The dependency-free harness starts node-http-server in a child process on 127.0.0.1 with an OS-assigned port. The parent creates temporary fixtures and drives real requests through Node's HTTP client, giving the server and measurement driver independent event loops. Every measured response passes status, header, and exact-body validation.
| Evidence | Contract | Route |
|---|---|---|
| Local developer run | Readable throughput plus p50, p95, and p99 latency for five public server paths. | npm run benchmark |
| Integration verification | All scenarios execute; metrics stay finite and ordered; CLI validation returns a clear failure. | npm run test:integration |
| Canonical CI evidence | Ubuntu Node 24.18.0 JSON rendered with environment, profile, throughput, and percentile data. | Latest benchmark result |
Coverage configuration
Node-only coverage through a small adapter.
vanilla-test.config.json runs test/coverage.js and includes server/*.js plus server/*.mjs. test/suites.js is the shared, dependency-free manifest: it walks sorted *.test.js files under Unit, Functional, Integration, then Regression. Both test/run.js and the coverage adapter consume that manifest, keeping targeted scripts, the full suite, and coverage on the same exact source list.
The adapter starts Node's native TAP reporter and returns status, counts, and unique descriptions for all 156 leaf cases. The configuration timeout is 120 seconds.
| Native V8 metric | Per-file gate | Ubuntu Node 24.18.0 |
|---|---|---|
| Executable ranges (statements) | 90% | 92.27% · report only |
| Executable lines | 90% | 92.83% |
| Function root ranges | 90% | 98.24% |
| Nested block ranges (branches) | 85% | 90.64% |
Generated evidence
Know which artifact answers which question.
| Path | Purpose | Committed? |
|---|---|---|
coverage/node/index.html | Primary browsable Node report published on Pages. | No; CI artifact/Pages output. |
coverage/node/lcov.info | LCOV interchange report. | No. |
coverage/node/coverage-summary.json | Machine-readable totals used by the badge adapter. | No. |
coverage/node/test-results.json | Authoritative ANSI-free status, counts, and unique leaf descriptions in runner execution order. | No. |
coverage/node/.vanilla-test-coverage.json | Ownership marker required before the report directory can be replaced safely. | No. |
coverage/badges/{lines,functions,branches}.json | Badge endpoints bundled with the coverage artifact and Pages site. | No. |
badges/{lines,functions,branches}.json | Deterministic raw-GitHub Shields endpoints used by README/site badges. | Yes. |
scripts/coverage.js reads the authoritative percentages from coverage-summary.json, chooses a color, and writes identical endpoint JSON to both badge locations.
git diff --exit-code -- badges immediately after coverage. Any difference from the canonical run fails the coverage job.Platform variance
Windows covers one extra filesystem guard.
| Environment | Test result | Statements | Lines | Functions | Branches | Why |
|---|---|---|---|---|---|---|
| Ubuntu Node 24.18.0 / published badges | 155 pass + 1 skip | 92.27% | 92.83% | 98.24% | 90.64% | The Windows alternate-data-stream test is skipped. |
| Windows Node 24.18.0 verification | 156 pass | 92.64% | 93.05% | 98.24% | 91.10% | The Windows ADS guard/test executes and covers its platform branch. |
GitHub Actions
Tests, evidence, package smoke, then Pages.
| Job | Runtime | Work | Artifact/output |
|---|---|---|---|
| Test matrix | Node 22.12.0 and 24 on Ubuntu | npm ci, npm test, npm run test:site. | Required before Pages. |
| Coverage | Node 24.18.0 on Ubuntu | npm run coverage plus root badge sync gate. | Complete vanilla-test-node-coverage report, including its ownership marker, retained 14 days. |
| Package smoke | Node 24 on Ubuntu | Asserts zero runtime deps/exact dev tool, checks packed exclusions, installs in a temporary consumer, exercises CJS/ESM/subpaths/two servers/CLI, cleans up, then makes a separate artifact pack. | node-http-server-v9-package, retained 14 days. |
| Benchmark | Node 24.18.0 on Ubuntu | Runs the standard validated five-scenario profile in separate server/driver processes. | node-http-server-benchmark JSON, retained 14 days and published as benchmarks/latest.json. |
| Pages assembly | Node 24 on Ubuntu | Runs the static-doc checker and assembles the docs, coverage report, badges, and benchmark JSON. | GitHub Pages artifact. |
| Pages deploy | Ubuntu | Deploys only from main after required jobs. | Published project site. |
Pull requests run tests, coverage, package smoke, and the benchmark. Main pushes and manual dispatches add Pages assembly and deployment after every prerequisite succeeds.
Practical workflow
Add one focused behavioral contract.
- Choose exactly one set.Use Unit for isolated Config behavior, Functional for normal public HTTP behavior, Integration for module/process/listener/benchmark boundaries, or Regression for a fixed failure/security boundary. Regression owns its 52 fixed failure and security contracts.
- Choose the owning source directory.Add the case under
test/unit/,test/functional/,test/integration/, ortest/regression/. The shared manifest recursively discovers sorted*.test.jsfiles for both normal tests and coverage. - Build isolated state.Use OS temporary roots, OS-assigned ports, ephemeral credentials, and existing helpers.
- Name and assert one contract.Keep the category prefix and a unique description. Check the public status, headers, body, lifecycle, emitted error, or CLI exit.
- Run the file directly.
node --test test/unit/config-defaults.test.jsornode --test test/integration/cli-serving.test.jsshortens the edit loop. - Run the suite and coverage.Use
npm test, thennpm run coverage. Inspect any per-file gate failure. - Finish with package smoke.
npm run test:packagecatches missing exports/files and CLI packaging errors.
node --test test/unit/config-defaults.test.js
node --test test/integration/cli-serving.test.js
npm run test:regression
npm testCoverage debugging
Turn a miss into one concrete branch.
- Open the primary report.Load
coverage/node/index.html, then open the file named by the gate. - Identify the exact miss.Start with the uncovered line/function/branch markers in the file named by the gate.
- Confirm reachability and platform.Decide whether the branch is a supported contract, an error path, or a Windows-only guard.
- Add the smallest behavioral case.Trigger the public outcome and assert cleanup/error behavior as well as the happy path.
- Rerun targeted, then full coverage.Verify the new assertion, the per-file gate, and badge generation.
- Check root badge diff.Commit intentional Ubuntu changes. After a Windows run, restore the root endpoints to canonical Ubuntu values.