Unit tests (Bun)
Unit tests run under Bun's built-in test runner. Use one of the following:
bun run test:unitbun test test/unitbun run test:coverage(writes text output and an LCOV (line coverage) report undercoverage/)make coverage- For roadmap item
9.1.1, run focused coverage with:
bun test --coverage \
test/unit/command-registry.test.ts \
test/unit/command-registry-validation.test.ts \
test/unit/context-key-service.test.ts \
test/unit/runtime-plugin-settings.test.ts
Until Bun branch-threshold enforcement is wired for this repository, use the
current codebase target from docs/velocetty-hyper-codebase.md §6.6.7.2 as
the local pass/fail basis for touched core modules: at least 60% line
coverage and 50% function coverage as the Bun-reported proxy for the
documented 50% branch target.
make test executes the shared unit suite through bun run test:unit:run,
which runs with --concurrent (maximum concurrency) as the default. Roadmap
item 9.3.1 removed the dedicated bootstrap-process quarantine by moving
renderer bootstrap assertions behind injected seams instead of file-scope
module mocks; roadmap item 9.3.2 removed the serialized guardrail from the
default local and CI unit gate; and roadmap items 9.3.3 through 9.3.7
hardened test-suite isolation so explicit concurrency can be the default.
When checking for order-dependent regressions, replay the unit suite with fixed seeds and explicit concurrency:
bun test --concurrent --randomize --seed 2444615283 test/unit
bun test --concurrent --randomize --seed 1337 test/unit
bun test --concurrent --randomize --seed 20260306 test/unit
To obtain a serialized reproduction path while diagnosing a suspected cross-file race, use one of the explicit diagnostic scripts instead of changing the default gate:
bun run test:unit:serialized
bun run test:unit:serialized:shuffled
For focused stress testing of specific suites under explicit concurrency, use targeted runs:
bun test --concurrent \
test/unit/rpc-client.test.ts \
test/unit/term-report-renderer.test.ts
This command supplements the default make test path and the seeded randomized
reruns above.
For roadmap item 9.3.4 and similar filesystem-fixture isolation work, use a
focused explicit-concurrency stress run against the directory-bootstrap helper
suite:
bun test --concurrent test/unit/ensure-directory-path.test.ts
Keep temporary-directory ownership and teardown scoped to each test, either
directly in the test or via a helper that returns per-test cleanup, so
ownership is not shared. Do not use a shared file-scope cleanup queue for
temporary roots in suites that must survive explicit --concurrent runs.
For roadmap item 9.3.5 and similar snapshot/bootstrap or CLI-config isolation
work, use a focused explicit-concurrency stress run against the snapshot and
CLI behaviour suites:
bun test --concurrent \
test/unit/v8-snapshot-util.test.ts \
test/unit/cli-api-behaviour.test.ts
Keep snapshot/bootstrap state isolated from globalThis during unit tests.
Prefer explicit bootstrap helpers that accept a test-owned runtime host and
return a restoration handle for any patched module loader state, so each test
can clean up the loader it installed without relying on file-scope teardown.
For CLI-config tests, do not share file-scope mutable mock state, shared
process.env mutation, or module-scope config-path capture across tests.
Prefer a per-test API factory with injected filesystem, registry, and
environment state so explicit --concurrent runs keep request history,
config-path resolution, and parsed-plugin state isolated per test instance.
For roadmap item 9.3.6 and similar concurrency-hotspot cleanup, use a focused
explicit-concurrency stress run against the remaining long-lived mock and
global hotspots:
bun test --concurrent \
test/unit/runtime-tab-provider-registration.test.ts \
test/unit/command-registry-compat.test.ts \
test/unit/config-import-json5.test.ts
Suites that must survive that probe must not rely on afterAll(...) to tear
down mock.module(...) registrations, temporary window installs, or other
process-global shims. Prefer per-test harness helpers that either return a
cleanup callback or accept injected dependencies directly. When a module under
test captures transport, config, or filesystem state at module scope, add the
smallest behaviour-preserving factory seam needed, so tests can provide
test-owned dependencies without long-lived module mocks.
For roadmap item 9.3.7 and similar timer/logger-dependent module work, use injected seams instead of process-global mutations:
- Pass timer implementations (
setTimeout,clearTimeout,setInterval,clearInterval) through component props or function options rather than replacingglobalThismethods. - Pass logger implementations (
console.error, etc.) through function options rather than replacingconsolemethods. - Keep global fallbacks for production code when seams are not provided.
- Test with explicit
--concurrentstress runs to verify isolation:
bun test --concurrent test/unit/notification.test.ts
bun test --concurrent test/unit/updater.test.ts
Suites that rely on timer or logger seams must not mutate global state during test execution; instead, provide test-doubles through the module's public interface.
End-to-end (E2E) tests (layered strategy)
End-to-end tests are split into two lanes and require packaged binaries in
dist/.
Fast lane (required on pull requests):
- Run
bun run test:e2e:fast(orbun run test:e2e). - Executes Bun-driven smoke checks in
test/e2e/. - Asserts renderer readiness and fails on critical renderer console errors.
- Supports
E2E_DRIVER=playwright|spawnoverrides; CI defaults to spawn-mode markers, with a macOS packaged-launch fallback that accepts missing renderer-ready marker output only when the process remains alive through an additional stability window bounded by remaining test-timeout budget. - Supports
E2E_DEBUG=1for verbose launch logs andE2E_CAPTURE=1for screenshot capture.
Deep lane (scheduled and release validation):
- Run
bun run test:e2e:deep. - Executes Playwright Test under Node.js using
playwright.e2e.config.tsandtest/e2e-deep/. - Installs Playwright Chromium on demand before execution.
- Validates the first interaction-path scenario (terminal input and rendered output).
- Retains full diagnostics on failures: stdout/stderr logs, renderer console logs, screenshots, and traces.
- Runs in CI on Linux for scheduled checks, manual
workflow_dispatch, and pushes tomasterandcanary. - Deep-lane failures on
masterandcanaryare release-blocking.
For screen readers: The following sequence diagram shows fast-lane execution, including main-process readiness/error markers consumed by Bun E2E assertions.
Figure 1: Fast-lane E2E sequence from Bun invocation to readiness/error assertions.
For screen readers: The following sequence diagram shows deep-lane execution through Playwright CLI/Test, including interaction-path assertion and artefact reporting.
Figure 2: Deep-lane E2E sequence from Bun command orchestration to Playwright interaction and reporting.
Before either lane, build packaged artefacts with bun run dist if they do not
already exist.