An esbuild failure, captured for display on the run's error page.
-
formatted: string
Pre-formatted esbuild message block.
-
type: string
Short error class used as the page heading (e.g.
'Build Error').
One group's esbuild output and in-flight build bookkeeping, kept warm between watch-mode
rebuilds. Lives at state.group.build, so it shares the group's lifetime rather than being
threaded alongside the config as a second, independently-passable bag.
-
activeRebuild: Promise<void> | null
Set when a parallel rebuild is in-flight during a watch-mode rerun. The
/tests.jsroute awaits this before serving, so Chrome can navigate concurrently while esbuild finishes. Cleared byrunafter the build settles. -
allTestCode: Buffer | string | null
Full test bundle source, or
nullbefore the first build completes. -
fallbackPage: FallbackPage | null
Replaces the normal test page for this run, or
nullwhen the run renders tests as usual. The web server's/route serves this page and the Playwright page is navigated there. Cleared at the start of every new build attempt. -
filteredTestCode: Buffer | string
Bundle filtered to files that failed on the previous run (used by re-run mode).
-
htmlPathsToRunTests: string[]
Absolute paths of every HTML file that will be opened in the browser to run tests.
-
lastBuildErrored: boolean
trueif the most recent build ended in an esbuild error. Keepsstate.watch.lastBuildEndMspinned to the last good build so a fix arriving after the error is never suppressed. Written by every run, read only in watch mode. -
preBuildPromise: Promise<void> | null
In-flight build promise started by
run.tsbefore Chrome setup completes (initial run) or beforerunis called (reruns), so esbuild races navigation. Consumed and cleared by the firstrun()call.
Handles to a pre-launched Chrome, available synchronously the moment it is spawned —
before the CDP endpoint is known. Enough to reap the process and its temp dir, which is all
the process.on('exit') safety net and shutdownPrelaunch() need.
-
proc: ChildProcess
The spawned Chrome child process.
-
shutdown: () => Promise<void>
Kills Chrome and awaits async temp-dir cleanup. Safe to call before CDP is ready, and idempotent with Chrome's own dead-on-arrival cleanup. Call before
process.exit().
Full resolved qunitx configuration for a single run, merging package.json settings,
CLI flags, and runtime state. Most fields are read-only after Config.setup() resolves;
underscore-prefixed fields are mutable runtime slots populated during the run lifecycle.
-
browser: "chromium" | "firefox" | "webkit"
Browser engine used for the test run (
'chromium'|'firefox'|'webkit'). -
cwd: string
Working directory this run resolves against: relative inputs, bare-specifier resolution inside the test bundle, and
--before/--afterhook paths.process.cwd()for the CLI; the JS API'scwdoption otherwise. Distinct from projectRoot, which is wherever the nearestpackage.jsonsits — running from a subdirectory keeps that subdirectory'snode_moduleson the resolution chain, exactly as Node itself would. -
extensions: string[]
File extensions treated as test files (default:
['js', 'ts']). -
failFast: boolean
When
true, abort the run after the first test failure (default:false). -
fsTree: FSTree
Current file-system snapshot, diffed in watch mode to detect added / removed files.
-
htmlPaths: string[]
Absolute paths to HTML fixture files that wrap the compiled test bundle.
-
output: string
Directory where the compiled test bundle and output HTML are written (default:
'tmp'). -
plugins: EsbuildPlugin[]
Custom esbuild plugins applied during the test bundle build. Loaded from
qunitx.config.{ts,js,mjs}in the project root. Common use cases: SFC formats like.vue(esbuild-plugin-vue-next), Svelte (esbuild-svelte), or any project-specific resolvers/loaders. -
port: number
TCP port the local test server listens on (default:
1234, auto-increments on conflict). -
projectRoot: string
Absolute path to the project root (directory containing
package.json). -
state: RunState
Mutable state for this run; see RunState for the sharing rules.
-
testFileLookupPaths: string[]
Paths searched when globbing for test files.
-
timeout: number
Maximum milliseconds to wait for the full test suite before timing out (default:
20000). -
webServer: HTTPServer
The run's HTTP server, exposed purely as
--before/--afterhook surface — qunitx itself never reads it back. Hooks use it to register extra routes (mock APIs) before tests start.
Live handles for the three resources allocated at the start of a test run. Passed through the run pipeline and closed together on shutdown.
-
browser: Browser
The Playwright browser instance.
-
page: Page
The Playwright page (tab) navigated to the test URL.
-
server: HTTPServer
The HTTP + WebSocket server that serves the test bundle and streams TAP events.
Running totals of test outcomes for a single test run. Mutated in place as TAP events arrive from the browser.
-
assertionsFailed: number
Number of test cases that threw an unexpected error outside of assertions.
-
failed: number
Number of test cases that had at least one failing assertion.
-
passed: number
Number of test cases where every assertion passed.
-
skipped: number
Number of test cases explicitly marked as skipped (not run).
-
todo: number
Number of test cases marked as todo (expected to fail, work in progress).
-
total: number
Total number of test cases registered.
The daemon's persistent, cross-run handles, lent to a single run via RunState.daemon.
-
browser: Browser
The daemon's Browser.
run()reuses it instead of launching, and does not close it. -
esbuildCache: EsbuildCache
Persistent incremental-context slot, keeping the module graph warm across daemon runs.
-
pageSlot: { page: Page | null; }
Persistent Page slot, reused across runs to save a
newPage()(~70-130ms). Read throughRunState.reusablePageSlot(), never directly — reuse is only valid for single-group runs.
A ChromeHandle plus the CDP endpoint, resolved once Chrome is listening.
-
cdpEndpoint: string
The
ws://URL exposed by Chrome's CDP remote debugging endpoint.
A slot holding esbuild's incremental build context plus the key it was built for.
Two lifetimes share this shape: the per-process one on BuildState (watch mode)
and the daemon's persistent one, which survives across runs. buildIncrementally takes
either — it disposes and recreates the context whenever the key changes.
-
context: BuildContext | null
Live esbuild incremental context, or
null/absent before the first build. -
contextKey: string
Cache key for
context:allTestFilePaths.join('\0'). Invalidated when files change.
Per-source-file line coverage, accumulated across every executed bundle. Keyed by absolute source path. Lines are 1-based, matching editor/lcov conventions.
-
coverable: Set<number>
1-based line numbers that the source map attributes to executable bundle positions.
-
covered: Map<number, number>
1-based line number → highest V8 hit count observed for that line.
-
sourceContent: string | null
Verbatim original source text (from the map's
sourcesContent), for the HTML report.
RunState scoped to a single concurrent group — one fresh object per group of a run.
-
build: BuildState
This group's bundle output and build bookkeeping.
-
groupMode: boolean
truewhile running as one of several concurrent groups. -
index: number
Index within the run's group array;
0for watch and single-group runs. -
lastQUnitResult: QUnitResult | null
QUNIT_RESULT delivered via the WS 'done' message; avoids a page.evaluate() CDP round-trip.
-
lastRanFiles: string[] | null
Test files this group ran on the last run. Failure attribution falls back to this when a failing assertion's stack can't be resolved to one file — scoped per group so an unattributable failure blames only the files that group ran, not the whole invocation.
-
pendingConsoleHandlers: Set<Promise<void>> | null
In-flight console handler promises; awaited before browser/page close so Firefox BiDi round-trips complete.
-
phase: "bundling" | "connecting" | "loading" | "running" | "done"
Current lifecycle phase of this group's run.
-
selectors: QUnitSelector[] | undefined
Exact test selections for this group, derived from
lineTargets. Applied in the browser viaQUnit.config.testFilter, which QUnit ANDs afterfilter/module. Per-group: each line-targeted file runs as its own group so untargeted files stay unfiltered. -
signals: RunSignals
Callbacks the run pipeline waits on, resolved as the browser reaches each milestone.
-
sourceMapDecoder: SourceMapDecoder | null
Decoded inline source map for this group's bundle; resolves stack frames to original sources.
-
testEndCounts: Map<string, number>
Tracks
testEndarrivals per test fullName in this group's run. Reset in lockstep with the run counter — explicitly NOT on every WS 'connection' event, which was the bug that broke no-html-test in CI run 26042614416. -
wsConnectionCount: number
Diagnostic-only: how many distinct WS connections this group's wss handler has accepted. Reset per
WebServer.setupcall. > 1 means the browser opened multiple WebSocket connections within one run — the prime suspect for the 2× test-execution flake (WS retry path in the injected runtime).
The run's resolved HTML fixtures and the assets they reference. Populated once by
buildCachedContent and not written again, so every concurrent group can share one copy.
-
assets: Set<string>
Asset paths (scripts, stylesheets) discovered inside the user's HTML fixture.
-
dynamicContentHTMLs: Record<string, string>
HTML pages whose bundle content is injected at request time, keyed by server-relative path.
-
mainHTML: { filePath: string | null; html: string | null; }
The primary HTML page: its path on disk and its resolved content.
-
staticHTMLs: Record<string, string>
Static HTML pages served verbatim, keyed by their server-relative path.
One collected JUnit <testcase> — accumulated per testEnd and serialized into
junit.xml at run end when --reporter=junit is active.
-
classname: string
Suite name: the QUnit module path (fullName minus the test name).
-
failureDetail: string
Concatenated failing-assertion messages + resolved stacks (failed cases only).
-
failureMessage: string
First failing assertion's message (failed cases only).
-
name: string
The test-case name (the last element of QUnit's fullName).
-
status: "passed" | "failed" | "skipped" | "todo"
Outcome of the test case.
-
time: number
Test runtime in seconds (QUnit reports ms; converted on record).
The run summary the browser-side runtime publishes on window.QUNIT_RESULT.
-
currentTest: string | null
Name of the test in flight, or
nullwhen none is running — the stall diagnostic. -
failedTests: number
Tests with at least one failing assertion.
-
finishedTests: number
Tests that reached
testEnd; short oftotalTestsmeans the run stalled. -
totalTests: number
Tests QUnit registered for this run.
One concurrent group of a run: the files bundled into a single page, and where that page's artifacts were written.
-
files: string[]
Absolute paths of the test files this group bundled and ran together.
-
index: number
Position in the run's group list, and the
group-<index>suffix onoutput. -
output: string
Absolute path of this group's build output directory.
Outcome totals and failure bookkeeping accumulated across every group of a single run. Every field here is mutated in place — see RunState for why replacement is unsafe.
-
aborted: boolean
Whether the browser confirmed it dropped this run's remaining queue —
qq,session.abort(), or an abortedsignal. Lives here rather than on the group because groups share this object by reference, so one aborted group marks the whole run without any cross-group plumbing. -
counter: Counter
Running test-outcome counts, mutated in place as TAP events arrive.
-
coverage: CoverageFileMap | null
Accumulator for per-source line coverage when
coverageis enabled;nullwhen it is off. Reassigned only byRunState.reset(a fresh Map per run), never by a group. -
failedFiles: Set<string>
Absolute paths of test files with ≥1 failure in the current run, attributed per-test via source maps. Every group adds into this one set; persisted to the failure cache at run end.
-
failedTests: FailedTestRecord[]
Per-test metadata for the current run's failures; accumulated alongside
failedFiles.
One-shot callbacks wiring the browser's progress back into the run pipeline. Each is installed by the code that awaits it and fired by the web server as the corresponding event arrives.
-
onTestsJsServed: (() => void) | null
Resolves when the test bundle JS has been served to the browser at least once.
-
onWsOpen: (() => void) | null
Resolves when the WebSocket connection from the browser page is established.
-
resetTestTimeout: (() => void) | null
Resets the inactivity timeout; called on each TAP progress event.
-
testRunDone: (() => void) | null
Resolves when the browser signals that the test run is complete.
Mutable state for one test run, kept separate from the resolved settings on Config.
-
aborters: Set<() => void>
One callback per live server that tells its connected pages to drop the rest of the QUnit queue — what
qq,session.abort()and an abortedsignalall go through. -
console: Console
Where this run's text goes: the TAP document, every reporter line, every
#diagnostic and every forwarded page log.processConsolefor the CLI,silentConsolefor a programmatic run that only wants the result value. Shared by reference across concurrent groups. -
daemon: DaemonState | null
Non-null exactly when this run is executing inside the persistent daemon process — it is the daemon-mode flag as well as the handles. Daemon runs reuse the shared browser, suppress the per-connection TAP header, and leave that browser open at the end of the run.
-
group: GroupState
RunState for this group only. The group spread replaces this object (everything else in
RunStateis shared by reference), so it is the one place per-group slots may live. -
groupCount: number
Number of concurrent groups in this run; 1 for watch and single-group runs.
-
groups: RunGroup[]
How this run's files were split across those groups — the descriptive record
RunResultreports. Assigned once per run alongsidegroupCountand shared by reference, so a group can read the whole split rather than only its own slice. -
htmlAssets: HtmlAssets
HTML fixtures and their referenced assets, resolved once by
buildCachedContentbefore any group config is spread off. Frozen from that point on, so all groups share one copy. -
reporters: Reporter[]
Active reporter instances for this run, built by
Reporters.createinConfig.setup. One set for the whole run, so a stateful reporter sees every group rather than one slice. -
results: RunResults
Whole-run accumulators, shared by reference across every concurrent group.
-
signal: AbortSignal
Cancels this run when it fires, or absent when nothing can. Carried here rather than threaded alongside the config because it is per-run input like everything else in
state— and it is what lets a verb reach it from the resolved config instead of re-reading the raw arguments. -
watch: WatchState
File-watcher build bookkeeping. Only meaningful in watch mode, where there is one group.
Build bookkeeping owned by the file watcher, used to decide whether a filesystem event should dispatch a rebuild. Watch mode runs exactly one group, so nothing here is contended.
-
building: boolean
truewhile esbuild is actively compiling. -
builtContentHash: Record<string, string>
Per-file content hash of what was last dispatched to a build. Both the fs.watch change handler and the macOS/Deno rescan compare against this instead of mtime — mtime has 1-second resolution on some filesystems (macOS/HFS+), so rapid same-second writes with different content are indistinguishable by mtime; the hash catches them and drops echoes.
-
justAddedAt: Map<string, number>
filePath → msof when each file was last processed as an 'add', so a 'change' echo arriving inside ADD_SUPPRESS_WINDOW_MS can be suppressed. -
justAddedFiles: Set<string>
File paths added since the last build, used to decide whether a rebuild is needed.
-
lastBuildEndMs: number
Timestamp (ms) of the most recent successful build, used for debounce logic.
0before the first build. -
pendingBuildTrigger: (() => void) | null
Queued build-trigger callback; fires once the in-progress build completes.
Absolute source path → its accumulated FileCoverage.
| { kind: "no-tests"; files: string[]; }
Why a run is showing something other than its tests: the last esbuild run failed, or every
test file compiled but registered 0 QUnit tests (files holds their display paths).
Snapshot of the project's file-system structure: a map of relative paths to null.
Diffed against a fresh snapshot in watch mode to detect added or removed test files.
Usage
import * as mod from "lib/types.ts";