From 6763fead60153ada1e3748fe83a95712f8416ddb Mon Sep 17 00:00:00 2001 From: sangwook Date: Sun, 7 Jun 2026 11:35:37 +0900 Subject: [PATCH 1/2] doc: add test reporter event lifecycle diagram Document the lifecycle of node:test reporter events under Class: TestsStream, with an ASCII diagram that distinguishes declaration-order events from their execution-order twins (test:dequeue/test:complete), the leaf vs suite flow, and the run-level finale. Fixes: https://github.com/nodejs/node/issues/51908 Signed-off-by: sangwook --- doc/api/test.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/doc/api/test.md b/doc/api/test.md index 573f2da98f9d..338af410720f 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -3578,6 +3578,65 @@ Global events are emitted once per test run: The root test also emits [`'test:plan'`][] and [`'test:diagnostic'`][] events at the end of the run to report run level totals. +### Event lifecycle + +The tables above group the events; the diagram below places them on a +timeline. The declaration ordered events form the main spine, buffered so that +a reporter sees them in source order, while each execution ordered twin is +emitted immediately, when the work actually happens. In particular, +[`'test:start'`][] marks when a test begins _reporting_ its own and its +subtests' status, not when its body begins executing; that moment is +[`'test:dequeue'`][]. + +```text + node:test reporter event lifecycle + main spine = DECLARATION order (buffered; matches source order) + right side = EXECUTION order (emitted immediately); ◄ marks each twin + + LEAF TEST + ───────── + ┌──────────────┐ test:enqueue + │ test:start │ ◄──── twins ──── (queued for execution; + └──────────────┘ type: 'suite' | 'test') + │ begins REPORTING test:dequeue + │ (not the start of (about to run; emitted right + │ the test body) before the test body runs) + │ + │ [ between the twins, on the execution timeline, the test + │ body runs: context.log() emits test:log live, and + │ test:stdout / test:stderr stream with --test ] + │ + ▼ + ┌───────────────────────┐ + │ test:pass │ test:fail │ ◄──── twin ──── test:complete + └───────────────────────┘ result (details.passed says which) + │ + ▼ + test:diagnostic the test's own context.diagnostic() messages, + buffered while it runs, flushed after its result + + + SUITE / PARENT TEST (each subtest is the whole LEAF flow above) + ─────────────────── + test:start ─► [ full flow of each subtest ... ] ─► + test:plan (count = subtests) ─► test:pass │ test:fail ─► + test:diagnostic + + + RUN-LEVEL FINALE (root, after all top-level tests) + ──────────────── + test:plan top-level count + │ + ▼ + test:diagnostic x N tests, suites, pass, fail, cancelled, + │ skipped, todo, duration_ms (+ coverage errors) + ▼ + test:coverage only if coverage is enabled + │ + ▼ + test:summary ─► stream ends +``` + ### Event: `'test:coverage'` * `data` {Object} From d460d296b2dfbe391590fcc300e3a41748c3e147 Mon Sep 17 00:00:00 2001 From: sangwook Date: Tue, 25 Aug 2026 20:42:36 +0900 Subject: [PATCH 2/2] doc: note test:interrupted in the lifecycle The diagram only covered the normal path, ending at test:summary. Add an INTERRUPTION branch: on SIGINT the run exits before the buffered declaration-ordered events are flushed, so neither the run-level finale nor the interrupted tests' own results are emitted. Signed-off-by: sangwook --- doc/api/test.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/api/test.md b/doc/api/test.md index 338af410720f..1b6ef5ae0e8e 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -3635,6 +3635,15 @@ subtests' status, not when its body begins executing; that moment is │ ▼ test:summary ─► stream ends + + + INTERRUPTION (SIGINT, e.g. Ctrl+C, while tests are still running) + ──────────── + test:interrupted the innermost tests still running at that moment + │ (not emitted if none were running) + ▼ + the run exits immediately — the buffered spine never flushes, so + neither the finale above nor those tests' own results are emitted ``` ### Event: `'test:coverage'`