@descryy/runtime-test-runner 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collector-version.d.ts +10 -0
- package/dist/collector-version.d.ts.map +1 -0
- package/dist/collector-version.js +12 -0
- package/dist/collector-version.js.map +1 -0
- package/dist/go-test.d.ts +81 -0
- package/dist/go-test.d.ts.map +1 -0
- package/dist/go-test.js +224 -0
- package/dist/go-test.js.map +1 -0
- package/dist/graph-mapping.d.ts +44 -0
- package/dist/graph-mapping.d.ts.map +1 -0
- package/dist/graph-mapping.js +72 -0
- package/dist/graph-mapping.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/jest-reporter.d.ts +72 -0
- package/dist/jest-reporter.d.ts.map +1 -0
- package/dist/jest-reporter.js +110 -0
- package/dist/jest-reporter.js.map +1 -0
- package/dist/playwright-reporter.d.ts +67 -0
- package/dist/playwright-reporter.d.ts.map +1 -0
- package/dist/playwright-reporter.js +93 -0
- package/dist/playwright-reporter.js.map +1 -0
- package/dist/reporter.d.ts +35 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +74 -0
- package/dist/reporter.js.map +1 -0
- package/dist/swift-xctest.d.ts +138 -0
- package/dist/swift-xctest.d.ts.map +1 -0
- package/dist/swift-xctest.js +384 -0
- package/dist/swift-xctest.js.map +1 -0
- package/dist/test-runner-collector.d.ts +370 -0
- package/dist/test-runner-collector.d.ts.map +1 -0
- package/dist/test-runner-collector.js +1014 -0
- package/dist/test-runner-collector.js.map +1 -0
- package/dist/vitest-reporter.d.ts +76 -0
- package/dist/vitest-reporter.d.ts.map +1 -0
- package/dist/vitest-reporter.js +131 -0
- package/dist/vitest-reporter.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §17's test-runner observation: **`node:test` (RT-073), Jest and Vitest
|
|
3
|
+
* (RT-123)**, each observed through that runner's own structured reporter
|
|
4
|
+
* API rather than TAP, a JSON summary file, or any other printed format.
|
|
5
|
+
*
|
|
6
|
+
* ## Three reporters, one envelope, no per-runner branch below this line
|
|
7
|
+
*
|
|
8
|
+
* The per-runner knowledge is *what a runner's own API calls things*, and
|
|
9
|
+
* that only exists inside the runner's process. So each runner gets a
|
|
10
|
+
* reporter that speaks its API (`reporter.ts`, `jest-reporter.ts`,
|
|
11
|
+
* `vitest-reporter.ts`) and writes one shared NDJSON envelope — node:test's
|
|
12
|
+
* own event and field names, kept because they were first. Everything from
|
|
13
|
+
* `createEventTranslator` down is runner-agnostic, the same boundary rule
|
|
14
|
+
* the IR has. The only per-runner logic is `PROFILES` below: how a command
|
|
15
|
+
* is recognised, what it is refused for, and which flags are injected.
|
|
16
|
+
*
|
|
17
|
+
* ## The defect a second runner exposed in code that had already shipped
|
|
18
|
+
*
|
|
19
|
+
* A `test.skip` emits **`test:pass` carrying `skip: true`** on node:test,
|
|
20
|
+
* and the translator mapped every `test:pass` to TEST_PASSED — so a
|
|
21
|
+
* skipped test was evidence of a passing one, the shape this checklist
|
|
22
|
+
* exists to ban, invisible because every fixture was fully-running. They
|
|
23
|
+
* are counted now, not emitted; see `TraceCoverage.notRun`.
|
|
24
|
+
*
|
|
25
|
+
* The node:test notes below still describe what this file's node path
|
|
26
|
+
* does, unchanged.
|
|
27
|
+
*
|
|
28
|
+
* `test:start` / `test:pass` / `test:fail` translate directly into
|
|
29
|
+
* `TEST_STARTED` / `TEST_PASSED` / `TEST_FAILED` Evidence, with the real
|
|
30
|
+
* `file`/`line`/`column` Node's own reporter stream already carries —
|
|
31
|
+
* `reliability: "self-contained"`, the same class a Python traceback or
|
|
32
|
+
* Ruby backtrace gets, since this came from the runtime's own captured
|
|
33
|
+
* state, not derivation.
|
|
34
|
+
*
|
|
35
|
+
* **Discovery is declared, never inferred** (RT-032's own precedent):
|
|
36
|
+
* `discoverRunner` refuses a command that names none of the three runners
|
|
37
|
+
* it observes, rather than sniffing `package.json`/lockfiles to guess which
|
|
38
|
+
* runner a project uses. Also refuses a command that already carries its
|
|
39
|
+
* own `--test-reporter` — safely co-existing with an unknown pre-existing
|
|
40
|
+
* reporter configuration (matching destinations positionally, possibly
|
|
41
|
+
* conflicting output) is real complexity this collector does not attempt
|
|
42
|
+
* to get right blindly; a caller who wants both gets an honest refusal
|
|
43
|
+
* naming why, not a best-effort guess.
|
|
44
|
+
*
|
|
45
|
+
* **Trace capture (RT-074): declared, via `TestContext.diagnostic()`, not
|
|
46
|
+
* inferred from anything.** A test that makes a backend call and wants its
|
|
47
|
+
* TEST_PASSED/TEST_FAILED evidence to correlate with that call's backend
|
|
48
|
+
* evidence calls `t.diagnostic("requestId: <the id it used>")` (and/or
|
|
49
|
+
* `traceId: ...`) — a real node:test API, surfaced as its own
|
|
50
|
+
* `test:diagnostic` reporter event, distinguishable from suite-level
|
|
51
|
+
* summary diagnostics by carrying the same `file`/`line` as the test
|
|
52
|
+
* itself. Nothing here guesses a request id from timing or proximity; a
|
|
53
|
+
* test that says nothing gets `requestId: null`, same as before.
|
|
54
|
+
*
|
|
55
|
+
* **TEST_CASE graph mapping (RT-076): `payload.qualifiedName`, not
|
|
56
|
+
* `payload.name`, is what a real graph resolves against.** node:test's own
|
|
57
|
+
* events carry only a test's innermost title; `adapter-typescript`'s
|
|
58
|
+
* TEST_CASE node name is the full `describe()` chain, space-joined ahead
|
|
59
|
+
* of the title. `SuiteStack` (below) reconstructs that chain purely from
|
|
60
|
+
* the reporter stream this collector already reads. `graphNodeId` on
|
|
61
|
+
* emitted evidence is still always null here, same as every other
|
|
62
|
+
* collector — `graph-mapping.ts`'s `resolveObservedTestCase` is what a
|
|
63
|
+
* caller holding both the store and the graph driver uses to resolve and
|
|
64
|
+
* attribute it, after `write()`, the same way `vertical-slice` already
|
|
65
|
+
* does for every other evidence type.
|
|
66
|
+
*
|
|
67
|
+
* **A note for whoever next mutation-tests this file (RT-080).** This
|
|
68
|
+
* package's own tests import `@descryy/runtime-test-runner` by package
|
|
69
|
+
* name, resolving through `exports` to `dist/` — not `../src/*.ts`
|
|
70
|
+
* directly. Mutating this file and re-running with a bare `node --test
|
|
71
|
+
* <file>` proves nothing: the compiled `dist/` is untouched and the
|
|
72
|
+
* mutation is never in the code path actually executed, an inert check
|
|
73
|
+
* that reads as a passing safety net. Always rebuild between mutate and
|
|
74
|
+
* run — `npm test` at the repo root does this automatically (`npm run
|
|
75
|
+
* build && node --test ...`); a scoped `npx tsc -b packages/test-runner`
|
|
76
|
+
* before a scoped `node --test packages/test-runner/test/*.test.ts` also
|
|
77
|
+
* works and is faster while iterating on one file.
|
|
78
|
+
*/
|
|
79
|
+
import { type ManagedProcess } from "@descryy/runtime-controller";
|
|
80
|
+
import type { Collector, EmitFn, TestRunnerConfiguration } from "@descryy/runtime-contracts";
|
|
81
|
+
/**
|
|
82
|
+
* §2 (RT-?): the contracts type, not a look-alike -- `ExecutionConfiguration.testRunner`
|
|
83
|
+
* IS this shape, the same "one type, not two that could drift" precedent
|
|
84
|
+
* `BrowserConfiguration`/`BrowserSessionOptions` already set (RT-068). Kept
|
|
85
|
+
* as a re-export so every existing `@descryy/runtime-test-runner` import
|
|
86
|
+
* of `TestRunnerConfiguration` still resolves.
|
|
87
|
+
*/
|
|
88
|
+
export type { TestRunnerConfiguration } from "@descryy/runtime-contracts";
|
|
89
|
+
export interface TestRunnerCollectorOptions {
|
|
90
|
+
readonly configuration: TestRunnerConfiguration;
|
|
91
|
+
/** Joins emitted Evidence back to a named service, same convention as every other collector. Omit for a standalone test run with no corresponding service. */
|
|
92
|
+
readonly service?: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Which runner a declared command names. The value is carried through
|
|
96
|
+
* discovery rather than re-derived, so nothing downstream re-parses a
|
|
97
|
+
* command string it has already been told the answer for.
|
|
98
|
+
*/
|
|
99
|
+
export type RunnerKind = "node:test" | "jest" | "vitest" | "junit" | "xunit" | "playwright" | "pytest" | "rspec" | "phpunit" | "minitest";
|
|
100
|
+
/**
|
|
101
|
+
* The version of the NDJSON envelope every reporter speaks (RT-130).
|
|
102
|
+
*
|
|
103
|
+
* ## Why a version, and why now rather than when it first hurts
|
|
104
|
+
*
|
|
105
|
+
* The three reporters that exist today are TypeScript in this package,
|
|
106
|
+
* compiled by the same `tsc -b` as the translator — so they cannot drift
|
|
107
|
+
* from it without the build saying so. **The JUnit listener will not be**:
|
|
108
|
+
* it is a Java source built by a separate step, and a compiled artifact
|
|
109
|
+
* that still runs while the envelope moves underneath it produces *wrong
|
|
110
|
+
* events*, not a build error.
|
|
111
|
+
*
|
|
112
|
+
* That is the failure the placement argument was really about. Wiring a
|
|
113
|
+
* build step can only tell you a file did not compile; it cannot tell you
|
|
114
|
+
* the thing that *did* compile is no longer telling the truth. A version
|
|
115
|
+
* in the stream can, at the moment it would otherwise be believed.
|
|
116
|
+
*
|
|
117
|
+
* **Landed before the first out-of-band reporter exists, deliberately.** A
|
|
118
|
+
* version added afterwards has nothing to check on the transition it was
|
|
119
|
+
* added for: the first listener would speak an unversioned envelope, and
|
|
120
|
+
* the absence-is-an-error rule below could not be turned on without
|
|
121
|
+
* breaking it.
|
|
122
|
+
*
|
|
123
|
+
* Bump this only when the envelope's *meaning* changes for an existing
|
|
124
|
+
* field. Adding an optional field a reporter may omit — `skipReason`,
|
|
125
|
+
* `isSuite`, `qualifiedName` — is not a bump: an older reporter that never
|
|
126
|
+
* sets it is still telling the truth, and the translator already has a
|
|
127
|
+
* documented answer for its absence.
|
|
128
|
+
*/
|
|
129
|
+
export declare const ENVELOPE_VERSION = 1;
|
|
130
|
+
/** The handshake line every reporter emits before its first event. */
|
|
131
|
+
export declare const ENVELOPE_HANDSHAKE_TYPE = "descry:envelope";
|
|
132
|
+
export type EnvelopeVerdict =
|
|
133
|
+
/** A handshake line, consumed here — never translated into an event. */
|
|
134
|
+
{
|
|
135
|
+
readonly kind: "handshake";
|
|
136
|
+
}
|
|
137
|
+
/** Not a handshake and not translatable: ordinary noise on stdout. */
|
|
138
|
+
| {
|
|
139
|
+
readonly kind: "ignore";
|
|
140
|
+
}
|
|
141
|
+
/** A translatable event from a reporter speaking this envelope. */
|
|
142
|
+
| {
|
|
143
|
+
readonly kind: "event";
|
|
144
|
+
}
|
|
145
|
+
/** The reporter cannot be believed; `reason` goes to COLLECTOR_ERROR. */
|
|
146
|
+
| {
|
|
147
|
+
readonly kind: "refuse";
|
|
148
|
+
readonly reason: string;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* The envelope gate, a function of its own because the case it exists for
|
|
152
|
+
* **cannot be reached end to end** (RT-130).
|
|
153
|
+
*
|
|
154
|
+
* Measured: node:test redirects a test's stdout — the patched
|
|
155
|
+
* `process.stdout.write` and the raw fd alike — and re-emits its output as
|
|
156
|
+
* a `test:stdout` event. So a fixture cannot put a stale handshake on the
|
|
157
|
+
* wire, and there is no way to drive the mismatch path through a real
|
|
158
|
+
* `node --test` run. That is a genuine safety property of the design (a
|
|
159
|
+
* test's own `console.log` can never be mistaken for a reporter line) and
|
|
160
|
+
* simultaneously the reason this logic is a pure function with its own
|
|
161
|
+
* tests rather than four lines inside `start()`.
|
|
162
|
+
*
|
|
163
|
+
* Stated rather than left as a coverage gap: the wiring is asserted end to
|
|
164
|
+
* end — a real run declares version 1, produces no `COLLECTOR_ERROR`, and
|
|
165
|
+
* the handshake never becomes an event — and the refusal is asserted here.
|
|
166
|
+
*/
|
|
167
|
+
export declare function createEnvelopeGate(): {
|
|
168
|
+
inspect(parsed: unknown, isEvent: boolean): EnvelopeVerdict;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Why a test did not run, in terms no runner owns.
|
|
172
|
+
*
|
|
173
|
+
* - `disabled` — declared not to run (`test.skip`, `@Disabled`, xUnit `Skip=`)
|
|
174
|
+
* - `not-implemented` — declared as absent rather than switched off (`test.todo`)
|
|
175
|
+
* - `precondition-unmet` — ran real code and bailed on an assumption (JUnit's `aborted`)
|
|
176
|
+
* - `unspecified` — the runner reported a skip without saying which
|
|
177
|
+
*
|
|
178
|
+
* `not-implemented` exists because RT-124 collapsed node:test's `skip` and
|
|
179
|
+
* `todo` into one event with no way to tell them apart — "switched off" and
|
|
180
|
+
* "never written" are different facts about coverage, and that distinction
|
|
181
|
+
* was dropped silently in the change whose whole subject was not dropping
|
|
182
|
+
* distinctions silently. `precondition-unmet` is Lane A's JUnit finding
|
|
183
|
+
* (RT-088), landed with the vocabulary rather than after it.
|
|
184
|
+
*/
|
|
185
|
+
export type SkipReason = "disabled" | "not-implemented" | "precondition-unmet" | "unspecified";
|
|
186
|
+
export type RunnerDiscovery = {
|
|
187
|
+
readonly ok: true;
|
|
188
|
+
readonly kind: RunnerKind;
|
|
189
|
+
readonly command: string;
|
|
190
|
+
readonly args: readonly string[];
|
|
191
|
+
} | {
|
|
192
|
+
readonly ok: false;
|
|
193
|
+
readonly reason: string;
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* **Where the reporter flags land in argv is load-bearing for node, not
|
|
197
|
+
* cosmetic.** Measured while building RT-073: `node --test sample.test.mjs
|
|
198
|
+
* --test-reporter=... --test-reporter-destination=...` silently falls back
|
|
199
|
+
* to the default TAP reporter -- once node's `--test` argument parser sees
|
|
200
|
+
* a positional file argument, anything after it stops being read as a
|
|
201
|
+
* flag. `node --test --test-reporter=... --test-reporter-destination=...
|
|
202
|
+
* sample.test.mjs` works. `discoverRunner` only guarantees `--test` is
|
|
203
|
+
* present *somewhere* in `args`, not that it is the last flag before any
|
|
204
|
+
* file arguments (a caller may pass `node --test --concurrency=4
|
|
205
|
+
* some.test.mjs`, and the reporter flags need to land after `--test` but
|
|
206
|
+
* still before `some.test.mjs`) -- so this inserts them immediately after
|
|
207
|
+
* the `--test` token specifically, not at the end of the array.
|
|
208
|
+
*
|
|
209
|
+
* Jest and Vitest both use full CLI parsers (yargs / cac) that read flags
|
|
210
|
+
* anywhere, so theirs are appended. That is a real difference between the
|
|
211
|
+
* three and is why this is per-runner rather than one shared rule.
|
|
212
|
+
*/
|
|
213
|
+
export declare function withReporterFlags(args: readonly string[]): readonly string[];
|
|
214
|
+
/**
|
|
215
|
+
* Exported on its own so a caller can validate a configured command before
|
|
216
|
+
* ever attempting to spawn it — the same "refuse atomically before anything
|
|
217
|
+
* is spawned" shape `validateServicesConfiguration` already established.
|
|
218
|
+
*
|
|
219
|
+
* **Declared, never inferred** (RT-032's precedent): this reads the command
|
|
220
|
+
* the caller wrote and nothing else. It does not open `package.json`, a
|
|
221
|
+
* lockfile, or a config file to guess which runner a project uses, and a
|
|
222
|
+
* command it does not recognise gets a named refusal rather than a
|
|
223
|
+
* best-effort guess.
|
|
224
|
+
*/
|
|
225
|
+
export declare function discoverRunner(rawCommand: string): RunnerDiscovery;
|
|
226
|
+
export declare function reporterFlagsFor(kind: RunnerKind, args: readonly string[]): readonly string[];
|
|
227
|
+
/** `{}` for every profile that has no `reporterEnv` — `start()`'s merge then adds nothing. */
|
|
228
|
+
export declare function reporterEnvFor(kind: RunnerKind, args: readonly string[]): Record<string, string | undefined>;
|
|
229
|
+
/**
|
|
230
|
+
* The NDJSON envelope every runner's reporter emits — node:test's own event
|
|
231
|
+
* names and field names, kept as the shared shape because it was first and
|
|
232
|
+
* renaming it would churn a working translator for nothing. `reporter.ts`,
|
|
233
|
+
* `jest-reporter.ts` and `vitest-reporter.ts` all write this, which is why
|
|
234
|
+
* nothing below this line branches on which runner produced it.
|
|
235
|
+
*/
|
|
236
|
+
export interface NodeTestEvent {
|
|
237
|
+
readonly type: string;
|
|
238
|
+
readonly data: {
|
|
239
|
+
readonly name?: string;
|
|
240
|
+
/**
|
|
241
|
+
* The full `describe()` chain, space-joined ahead of the title, when
|
|
242
|
+
* the reporter could supply it directly. Jest and Vitest can; node:test
|
|
243
|
+
* cannot (its events carry only the innermost title), which is why
|
|
244
|
+
* `SuiteStack` exists and why this is optional rather than required.
|
|
245
|
+
*/
|
|
246
|
+
readonly qualifiedName?: string;
|
|
247
|
+
/** True for a test that did not run. Not a pass — see `TraceCoverage.notRun`. */
|
|
248
|
+
readonly skip?: boolean;
|
|
249
|
+
readonly todo?: boolean;
|
|
250
|
+
/**
|
|
251
|
+
* **Why it did not run** — a payload field rather than a second event
|
|
252
|
+
* type (RT-129), because the test for "does this need its own type" is
|
|
253
|
+
* whether collapsing it changes the answer to *was this code covered*.
|
|
254
|
+
* Skipped-vs-passed does, oppositely, and earned `TEST_SKIPPED` in
|
|
255
|
+
* RT-124. Every value here answers `notRun`, so nothing routes
|
|
256
|
+
* differently and what differs is the explanation.
|
|
257
|
+
*
|
|
258
|
+
* Set by each **reporter**, not derived here, for the same reason
|
|
259
|
+
* `isSuite` is: only the reporter knows what its runner can tell apart.
|
|
260
|
+
* `unspecified` is a real answer — Vitest reports `state: "skipped"`
|
|
261
|
+
* for both `.skip` and `.todo` (measured), so claiming either would be
|
|
262
|
+
* a guess dressed as a fact.
|
|
263
|
+
*
|
|
264
|
+
* Runner-agnostic by construction: no value may name a runner, the same
|
|
265
|
+
* boundary the translator itself keeps.
|
|
266
|
+
*/
|
|
267
|
+
readonly skipReason?: SkipReason;
|
|
268
|
+
/**
|
|
269
|
+
* True when this event describes a **container** (a `describe()` block)
|
|
270
|
+
* rather than a test case. Only node:test reports containers through
|
|
271
|
+
* the same channel as tests; Jest's and Vitest's per-test callbacks
|
|
272
|
+
* never fire for one, so their reporters never set this.
|
|
273
|
+
*/
|
|
274
|
+
readonly isSuite?: boolean;
|
|
275
|
+
readonly nesting?: number;
|
|
276
|
+
readonly file?: string;
|
|
277
|
+
readonly line?: number;
|
|
278
|
+
readonly column?: number;
|
|
279
|
+
readonly message?: string;
|
|
280
|
+
readonly details?: {
|
|
281
|
+
readonly duration_ms?: number;
|
|
282
|
+
readonly error?: {
|
|
283
|
+
readonly code?: string;
|
|
284
|
+
readonly failureType?: string;
|
|
285
|
+
readonly cause?: unknown;
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
export declare function isNodeTestEvent(value: unknown): value is NodeTestEvent;
|
|
291
|
+
/**
|
|
292
|
+
* `test:pass`/`test:fail` arrive from node's own reporter stream BEFORE any
|
|
293
|
+
* `t.diagnostic()` call inside that same test shows up as its own
|
|
294
|
+
* `test:diagnostic` event -- measured directly: for a passing test that
|
|
295
|
+
* calls `t.diagnostic("requestId: X")`, the real event order is
|
|
296
|
+
* `test:start`, `test:pass`, *then* `test:diagnostic`. Emitting
|
|
297
|
+
* TEST_PASSED/TEST_FAILED immediately would mean it goes out with
|
|
298
|
+
* `requestId: null` even when the test declared one one event later --
|
|
299
|
+
* and `EvidenceStore` has no path to correct a `requestId` after
|
|
300
|
+
* `write()` (`attribute()` exists only for `graphNodeId`, deliberately;
|
|
301
|
+
* see its own doc comment). So a result is held, not emitted immediately,
|
|
302
|
+
* until either a same-test diagnostic merges into it or a signal arrives
|
|
303
|
+
* that no more are coming for this test (the next `test:start`, or a
|
|
304
|
+
* diagnostic with no `file` -- node's own suite-level summary lines,
|
|
305
|
+
* which never carry one). A bounded, disclosed delay -- at most one test's
|
|
306
|
+
* duration, never batched until the whole run ends -- not a violation of
|
|
307
|
+
* this collector's own streaming-first design, RT-073's `pumpLines`.
|
|
308
|
+
*/
|
|
309
|
+
export interface TraceCoverage {
|
|
310
|
+
/** How many TEST_PASSED/TEST_FAILED results this collector has actually emitted. The denominator -- report against this, never against `idsPresent` alone, or "correlated 3 of 3" reads as full coverage when 40 tests ran and only 3 said anything. */
|
|
311
|
+
readonly testsObserved: number;
|
|
312
|
+
/** Of `testsObserved`, how many carried a real `requestId` and/or `traceId` via `t.diagnostic()`. */
|
|
313
|
+
readonly idsPresent: number;
|
|
314
|
+
/**
|
|
315
|
+
* Tests the runner reported as **not run** — `.skip` and `.todo`. Each
|
|
316
|
+
* also gets its own `TEST_SKIPPED` Evidence (RT-124); this is the count,
|
|
317
|
+
* for a caller that wants the denominator without scanning the store.
|
|
318
|
+
*
|
|
319
|
+
* **This collector used to report them as TEST_PASSED**, which is the one
|
|
320
|
+
* shape this checklist exists to ban, arriving through a runner's own API
|
|
321
|
+
* rather than through a summary line. Measured on node:test: a skipped
|
|
322
|
+
* test emits `test:pass` carrying `skip: true`, and a `test.todo` emits
|
|
323
|
+
* `test:pass` carrying `todo: true`; the translator mapped every
|
|
324
|
+
* `test:pass` to TEST_PASSED. Vitest reports both as `state: "skipped"`;
|
|
325
|
+
* Jest reports `.todo` as `status: "todo"` and omits `.skip` from its
|
|
326
|
+
* result callback altogether, so its count here is a floor, not a total —
|
|
327
|
+
* disclosed rather than presented as complete.
|
|
328
|
+
*
|
|
329
|
+
* **This was a bare counter in RT-123 and is now backed by a real
|
|
330
|
+
* event.** `RUNTIME_EVENT_TYPES` had no member for a test that did not
|
|
331
|
+
* run, so counting was the only honest thing a package could do without
|
|
332
|
+
* extending a shared vocabulary; RT-124 added `TEST_SKIPPED` with its
|
|
333
|
+
* three producers in one change. The counter stayed because it is the
|
|
334
|
+
* denominator — "12 passed" is never silently "9 passed and 3 that never
|
|
335
|
+
* ran" — but the fact is now attributable, with a source location and a
|
|
336
|
+
* qualified name that resolves to a `TEST_CASE` node.
|
|
337
|
+
*
|
|
338
|
+
* TEST_STARTED **is** still emitted for a skipped test — the runner does
|
|
339
|
+
* not know it will be skipped when it announces the start — so
|
|
340
|
+
* `testsObserved + notRun` is what reconciles against the TEST_STARTED
|
|
341
|
+
* count, not `testsObserved` alone.
|
|
342
|
+
*/
|
|
343
|
+
readonly notRun: number;
|
|
344
|
+
}
|
|
345
|
+
export declare function createEventTranslator(emit: EmitFn, service: string | undefined, processId: string): {
|
|
346
|
+
handle(event: NodeTestEvent): void;
|
|
347
|
+
flush(): void;
|
|
348
|
+
coverage(): TraceCoverage;
|
|
349
|
+
};
|
|
350
|
+
/**
|
|
351
|
+
* Feeds complete NDJSON lines from `managed`'s growing output buffer to
|
|
352
|
+
* `onLine`, exactly once each, as they arrive -- streaming-first, not
|
|
353
|
+
* batched until the process exits. A narrower, single-purpose relative of
|
|
354
|
+
* `orchestrator`'s `createPollingProcessOutputSource` (same buffer-growth
|
|
355
|
+
* assumption, same "ends only once the process is finished AND the buffer
|
|
356
|
+
* stopped growing" ordering) rather than a shared dependency on it: this
|
|
357
|
+
* collector only ever needs complete lines fed to a callback, not the
|
|
358
|
+
* general `ProcessOutputSource` shape, and taking a dependency on
|
|
359
|
+
* `@descryy/runtime-orchestrator` -- the assembly layer -- from a collector
|
|
360
|
+
* would invert the direction every other package in this repo depends in.
|
|
361
|
+
*/
|
|
362
|
+
export declare function pumpLines(managed: ManagedProcess, onLine: (line: string) => void, pollIntervalMs?: number): Promise<void>;
|
|
363
|
+
export interface TestRunnerCollector extends Collector {
|
|
364
|
+
/** Resolves once the spawned runner process has exited and every buffered line has been translated. Await this, not just `stop()`, to know the run finished. */
|
|
365
|
+
waitForCompletion(): Promise<void>;
|
|
366
|
+
/** How many observed tests actually carried a `t.diagnostic()`-declared correlation id, against how many were observed at all -- the denominator matters (RT-074): "N correlated" alone reads as full coverage no matter how small N is relative to the real test count. `{testsObserved: 0, idsPresent: 0}` before any result has been observed. */
|
|
367
|
+
traceCoverage(): TraceCoverage;
|
|
368
|
+
}
|
|
369
|
+
export declare function createTestRunnerCollector(options: TestRunnerCollectorOptions): TestRunnerCollector;
|
|
370
|
+
//# sourceMappingURL=test-runner-collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner-collector.d.ts","sourceRoot":"","sources":["../src/test-runner-collector.ts"],"names":[],"mappings":"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"}
|