Everything a finished run produced.
A run whose tests failed is a successful run. run() resolves with ok: false; it does
not reject. Rejection is reserved for the run not happening — a bad option, an unreadable
input, a project with no package.json. Distinguishing "the suite says no" from "the runner
could not answer" is the whole point of the split, and it is what lets catch mean something.
// Defined, not invoked: a real result comes back from `run()`. function summarize(result: RunResult) { return `${result.counts.passed}/${result.counts.total} passed in ${result.durationMs}ms`; }
ok: boolean
true when every test passed and nothing else went wrong.
exitCode: number
What the CLI would have exited with: 0 when ok, 1 otherwise.
durationMs: number
Wall-clock duration of the test phase, in milliseconds.
tests: TestResult[]
Every finished test, in the order the browser reported them.
The subset of tests that failed — the list you almost always want first.
files: string[]
Absolute paths of the test files this run executed — the ones scoped to, in a filtered watch rerun, rather than everything being watched.
failedFiles: string[]
Absolute paths of the test files with at least one failure, attributed via source maps.
console.* calls and uncaught errors from the page — warnings and errors unless debug.
Capped at the most recent MAX_BROWSER_LOGS; browserLogsDropped counts what was
dropped. The cap is not tidiness: unlike tests and notices, page output is bounded by nothing
— one for loop around console.warn produced 50,001 entries and 252 MB of retained heap.
The newest are kept because they are the ones adjacent to the failure being diagnosed.
browserLogsDropped: number
How many page-log entries were dropped to stay under the cap. 0 in every ordinary run.
coverage: CoverageSummary | null
Line coverage, or null when coverage was not requested.
junitXml: string | null
The JUnit XML document, when junit was requested. Written to disk as well.
startedAt: number
Epoch ms when the test phase began.
finishedAt: number
Epoch ms when it ended.
How the files were split across concurrent groups — one entry per group, never empty.
groups.length is the concurrency the run actually used; 1 for watch and single-file runs.
Worth having because the split is not reproducible from the outside: it is recomputed each
run from recorded timings and the core count. When a test only fails alongside a particular
neighbour, this is what identifies the neighbour — and
run({ inputs: result.groups[2].files }) re-runs that bundle on its own.
There is deliberately no URL here. A group's server is closed by the time this result
exists, so an address would be a link that never resolves; RunGroup.output is the
durable equivalent, still on disk, and it is what --open points a browser at.
status: "completed" | "aborted" | "failFast"
How the run finished: whether it got through everything it selected, and if not, what stopped
it. Distinct from RunResult.ok, which is the verdict — a completed run can be
entirely red, and an aborted one can have no failures at all.
A boolean aborted could not tell a suite that stopped at its first failure from one that
genuinely has two tests — both come back ok: false with a small counts.total — so the
three endings are named instead:
completed— every selected test reached an outcome.aborted— something cut it short:session.abort(), the CLI'sqq, or asignal. An already-aborted signal lands here too, having launched no browser at all.failFast—failFastwas set and a test failed, so the rest of the queue was dropped. Reported whenever the policy ended the run, including when the failure was the last test.
completed is the only one where counts.total is the whole selection. Check it before
reporting a red run as red, or a UI says "1 failure" about a suite it never finished.
What the run resolved to — see ResolvedRun.