Skip to main content

Testing

PreviewAvailable on: WindowsShips in the preview channel only. Not a stable release.

The suites, what each one is for, and what a passing run does and does not prove.

The suites

CommandScope
npm testThe parallel suite, then the runtime suite
npm run test:parallelEverything except runtime-tagged tests
npm run test:runtimeRuntime-tagged tests, separate config
npm run test:harnessHarness suite
npm run test:rigSimulation rig
npm run test:packaged-self-testVerifies an actual packaged build

Vitest throughout, with a separate config per surface so a renderer test does not drag in daemon setup.

Why runtime tests are separated

Runtime-tagged tests need real processes, real timing, or a real terminal. They are slower and less parallelisable, so they run as their own pass. Excluding them from the parallel suite keeps the fast feedback loop fast.

Do not move a runtime test into the parallel suite to speed up CI. It will become flaky rather than fast.

The packaged self-test matters most

test:packaged-self-test runs against a built package rather than source. It is the only suite that can catch:

  • Resources missing from the package
  • A build that shipped without the Pi runtime
  • Path resolution that works in development and not when packaged
  • Shim and activation behaviour after installation

WARNING

An empty vendor/ directory silently produces a build without the Pi runtime. Build with NALA_REQUIRE_PI_RUNTIME=1 so this fails loudly. A green source test run says nothing about whether the package is complete.

What a passing run does not prove

Being explicit, because this codebase has been bitten by each of these:

Green tests do not proveBecause
The packaged build worksSource tests do not exercise packaging
Provider launch worksDepends on binaries and auth on the machine
A feature is proven end to endUnit coverage is not integration evidence
Behaviour on macOS or LinuxNeither is built or tested on a Windows host

The internal audit ledgers distinguish [SHIPPING] (observed working) from [DESIGNED] (code and contracts exist, never proven end to end). Keep that distinction when you claim something works.

Before changing durable behaviour

State owned by the daemon outlives a test run. When changing it:

  1. Add a test at the daemon boundary, not only in the client.
  2. Cover the failure code, not just the happy path — structured errors carry a retryable flag that callers branch on.
  3. Check restart behaviour: state that does not survive a daemon restart is not durable, whatever the test says.

Writing tests near the TUI

The TUI has substantial coverage (82 test files at 3.24.1-preview.11). Prefer testing the projection and command layers over asserting on rendered frames — frame assertions break on unrelated layout changes and teach you little.