Tests + measured Node coverage
Verify behavior before shipping.
Run 213 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: 213 unique leaf cases, plus the HTTP/2 parent counted in Node's 214-result summary. The Windows-only filesystem case is skipped on other platforms. |
npm run test:unit | Config and suite discovery in isolation. | Runs the 57 cases under test/unit/. |
npm run test:functional | Normal public server behavior. | Runs the 58 cases under test/functional/. |
npm run test:behavioral | Behavior-focused checks without isolated Unit contracts. | Selects the 156 Functional, Integration, and Regression cases from the shared manifest. |
npm run test:integration | Module, CLI, benchmark, HTTP/2, listener, stream, and filesystem boundaries. | Runs the 40 leaf cases under test/integration/. |
npm run test:regression | Previously fixed failures and security boundaries. | Runs the 58 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 and Node-only metadata, imports Node.js CommonJS/ESM/subpaths by bare package name, 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.test:behavioral composes the existing non-unit sets. It adds no duplicate cases or second test framework. Given the Node CLI is serving an SPA, when the client requests a deep route and a missing asset, then the route receives the SPA fallback while the missing asset remains 404. This exercises browser-facing content through the Node listener; it does not execute the package in a browser.Current suite
213 unique, focused cases in four sets.
Each of the 213 leaf cases owns one focused behavior contract within a selectable engineering set. The HTTP/2 parent groups its fifteen integration cases and is counted separately in Node's summary.
| Set | Source | Cases | Primary contract | Run alone |
|---|---|---|---|---|
| Unit | test/unit/ | 57 | Config defaults, HTTP/2 selection and isolation, deferred MIME state, routing mutation tracking, merging, validation, logger error handling, and suite discovery. | npm run test:unit |
| Functional | test/functional/ | 58 | Lifecycle, static HTTP, ranges, caching, compression quality, bodies, hooks, live routing, timeouts, logging, and deliberate dotfile opt-in. | npm run test:functional |
| Integration | test/integration/ | 40 | 15 module/CLI contracts, 3 benchmark harness contracts, 15 HTTP/2 contracts, and 7 listener, socket, stream, and filesystem boundary contracts. | npm run test:integration |
| Regression | test/regression/ | 58 | Previously fixed validation, lifecycle, range, path-security, hook, stream, filesystem, and logging failures. | npm run test:regression |
| Total | test/{unit,functional,integration,regression}/ | 213 | Unique leaf cases; Regression owns 58 fixed failure and security contracts. | npm test |
Source inventory
| Source file | Cases | Ownership |
|---|---|---|
test/unit/config-defaults.test.js | 10 | Loopback, static-file, server, deferred MIME resolution, error-header, domain, and MIME opt-out defaults. |
test/unit/config-http2.test.js | 5 | HTTP/2 defaults and opt-out, partial HTTPS merges, caller-mutation isolation, independent Config snapshots, and per-server protocol selection. |
test/unit/config-isolation.test.js | 14 | Snapshot, nested value, settings, inherited/frozen/deferred 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 | 7 | Deferred/materialized MIME overlays and restoration of MIME, server, error, and error-header defaults. |
test/unit/config-routing.test.js | 5 | Routing revisions across root/domain assignments, domain-map mutations, replacements, and merges. |
test/unit/config-validation.test.js | 10 | Record validation, deferred-map 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 | 58 | 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 | 4 | Live CLI root serving, SPA routing, missing-asset behavior, and dotfile policy. |
test/integration/exports.test.js | 6 | CommonJS, ESM, Config, and MIME export identity. |
test/integration/http2.test.js | 15 | TLS negotiation and HTTP/1.1 fallback, authority routing, static responses, complete uploads, raw/buffered hooks, concurrent streams, errors, instance isolation, graceful closure, and cancellation. |
test/integration/server.test.js | 7 | Listener isolation, HTTPS wiring, binary/socket/SPA streams, abort cleanup, and NDJSON logging. |
test/regression/server.test.js | 58 | Permanent guards for fixed failure modes and security boundaries. |
| Total | 213 | One authoritative owner per behavior. |
test-results.json records the associated run's status, totals, and top-level descriptions; the nested HTTP/2 descriptions remain in the native runner output.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 |
| Core release comparison | Nine alternating 9.0.2/9.1.0 samples with raw data for targeted routing, hooks, Config, lifecycle, range, and Brotli paths. | Performance report |
| 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, summary counts, and unique top-level descriptions. Native output preserves all nested HTTP/2 case details. The configuration timeout is 120 seconds.
| Native V8 metric | Per-file gate | Recorded 9.1.1 baseline · Ubuntu/WSL Node 24.18.0 |
|---|---|---|
| Executable ranges (statements) | 90% | 90.30% |
| Executable lines | 90% | 92.12% |
| Function root ranges | 90% | 96.40% |
| Nested block ranges (branches) | 85% | 88.86% |
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 | ANSI-free status, summary counts, and unique top-level 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.
This recorded 9.1.1 comparison shows the platform difference in the 193-case baseline. The current 213-case suite includes the same Windows-only case.
| Environment | Test result | Statements | Lines | Functions | Branches | Why |
|---|---|---|---|---|---|---|
| 9.1.1 · Canonical Ubuntu/WSL Node 24.18.0 | 192 pass + 1 skip | 90.30% | 92.12% | 96.40% | 88.86% | The Windows alternate-data-stream test is skipped. |
| 9.1.1 · Windows Node 24.18.0 verification | 193 pass | Host-specific | Host-specific | Host-specific | Host-specific | 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 the Node-only boundary, zero runtime deps/exact dev tool, checks packed exclusions, installs in a temporary consumer, exercises Node.js 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 58 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.