@descryy/runtime-test-runner 0.3.0 → 0.4.1
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/LICENSE +6 -0
- package/dist/collector-version.d.ts +2 -6
- package/dist/collector-version.d.ts.map +1 -1
- package/dist/collector-version.js +2 -6
- package/dist/collector-version.js.map +1 -1
- package/dist/go-test.d.ts +24 -50
- package/dist/go-test.d.ts.map +1 -1
- package/dist/go-test.js +30 -68
- package/dist/go-test.js.map +1 -1
- package/dist/graph-mapping.d.ts +10 -28
- package/dist/graph-mapping.d.ts.map +1 -1
- package/dist/graph-mapping.js +16 -43
- package/dist/graph-mapping.js.map +1 -1
- package/dist/jest-reporter.d.ts +20 -46
- package/dist/jest-reporter.d.ts.map +1 -1
- package/dist/jest-reporter.js +28 -71
- package/dist/jest-reporter.js.map +1 -1
- package/dist/playwright-reporter.d.ts +16 -34
- package/dist/playwright-reporter.d.ts.map +1 -1
- package/dist/playwright-reporter.js +22 -51
- package/dist/playwright-reporter.js.map +1 -1
- package/dist/reporter.d.ts +7 -19
- package/dist/reporter.d.ts.map +1 -1
- package/dist/reporter.js +18 -52
- package/dist/reporter.js.map +1 -1
- package/dist/swift-xctest.d.ts +40 -94
- package/dist/swift-xctest.d.ts.map +1 -1
- package/dist/swift-xctest.js +47 -105
- package/dist/swift-xctest.js.map +1 -1
- package/dist/test-runner-collector.d.ts +14 -1
- package/dist/test-runner-collector.d.ts.map +1 -1
- package/dist/test-runner-collector.js +10 -0
- package/dist/test-runner-collector.js.map +1 -1
- package/dist/vitest-reporter.d.ts +19 -43
- package/dist/vitest-reporter.d.ts.map +1 -1
- package/dist/vitest-reporter.js +30 -82
- package/dist/vitest-reporter.js.map +1 -1
- package/package.json +12 -7
package/dist/jest-reporter.js
CHANGED
|
@@ -1,62 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* `node:test`.
|
|
2
|
+
* Jest custom reporter (`--reporters=`), emitting the same NDJSON envelope
|
|
3
|
+
* `reporter.ts` emits for node:test.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
5
|
+
* Three reporters, one envelope, not three collectors: each runner speaks its
|
|
6
|
+
* own API and writes the shape `test-runner-collector.ts` reads
|
|
7
|
+
* (`{type: "test:start"|"test:pass"|"test:fail", data: {...}}`, kept as
|
|
8
|
+
* node:test's own names since it was first). `createEventTranslator` needs no
|
|
9
|
+
* per-runner branch; everything Jest-specific lives here.
|
|
7
10
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* them would churn a working translator for nothing.
|
|
11
|
+
* `testCaseResult.ancestorTitles` gives the real `describe()` chain, so
|
|
12
|
+
* `qualifiedName` is exact, not reconstructed (contrast node:test's `SuiteStack`,
|
|
13
|
+
* RT-076). Jest's `fullName` is used directly since it matches
|
|
14
|
+
* `adapter-typescript`'s TEST_CASE convention (`[...suite, title].join(" ")`)
|
|
15
|
+
* exactly (verified against a real run) — Vitest's `fullName` does not (joins
|
|
16
|
+
* with `" > "`), which is why `vitest-reporter.ts` rebuilds it and this doesn't.
|
|
15
17
|
*
|
|
16
|
-
* `
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* ## What Jest gives that node:test does not, and vice versa
|
|
21
|
-
*
|
|
22
|
-
* `testCaseResult.ancestorTitles` is the real `describe()` chain, so
|
|
23
|
-
* `qualifiedName` is exact rather than reconstructed — node:test forced
|
|
24
|
-
* `SuiteStack` to rebuild it from `nesting` because its events carry only
|
|
25
|
-
* the innermost title (RT-076). Emitting it directly is why the translator
|
|
26
|
-
* prefers a supplied `qualifiedName` over its own reconstruction.
|
|
27
|
-
*
|
|
28
|
-
* **Jest's own `fullName` is the same space-joined string** and is used
|
|
29
|
-
* here in preference to re-joining, since it is what Jest itself
|
|
30
|
-
* considers the test's full name. It matches `adapter-typescript`'s
|
|
31
|
-
* TEST_CASE convention (`[...suite, title].join(" ")`) exactly — verified
|
|
32
|
-
* against a real run, not assumed. Vitest's `fullName` does **not** (it
|
|
33
|
-
* joins with `" > "`), which is why `vitest-reporter.ts` rebuilds it and
|
|
34
|
-
* this one does not.
|
|
35
|
-
*
|
|
36
|
-
* **`onTestCaseStart` carries no location** — measured. Only
|
|
37
|
-
* `onTestCaseResult` does, and only when `--testLocationInResults` is
|
|
38
|
-
* passed. So TEST_STARTED for Jest has a `file` but null `line`/`column`,
|
|
39
|
-
* where node:test's has all three. Disclosed rather than filled in.
|
|
40
|
-
*
|
|
41
|
-
* ## `--testLocationInResults` is load-bearing, and its absence is silent
|
|
42
|
-
*
|
|
43
|
-
* Measured directly: without it, `testCaseResult.location` is `undefined`
|
|
44
|
-
* on every result. The collector still runs, still emits every event, and
|
|
45
|
-
* every one silently has no line or column — the same shape as RT-073's
|
|
46
|
-
* reporter-flag ordering bug, where the failure was "no error, wrong
|
|
47
|
-
* output". `withReporterFlags` injects it; it is not left to the caller.
|
|
18
|
+
* `onTestCaseStart` carries no location (measured); only `onTestCaseResult`
|
|
19
|
+
* does, and only with `--testLocationInResults`. Without that flag,
|
|
20
|
+
* `location` is silently `undefined` on every result (same failure shape as
|
|
21
|
+
* RT-073) — `withReporterFlags` injects it rather than leaving it to the caller.
|
|
48
22
|
*/
|
|
49
23
|
function write(type, data) {
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
// anyway) can never be mistaken for an event.
|
|
24
|
+
// one JSON value per line on stdout; collector ignores non-JSON lines (Jest's own
|
|
25
|
+
// progress output goes to stderr anyway)
|
|
53
26
|
process.stdout.write(JSON.stringify({ type, data }) + "\n");
|
|
54
27
|
}
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
// stream transform and must yield instead), since this reporter already
|
|
59
|
-
// writes every event the same way (RT-130).
|
|
28
|
+
// emitted at module load, before any test runs -- a plain stdout write is fine here
|
|
29
|
+
// since (unlike node:test's stream-transform reporter) everything else is written the
|
|
30
|
+
// same way (RT-130)
|
|
60
31
|
write("descry:envelope", { version: 1 });
|
|
61
32
|
export default class DescryJestReporter {
|
|
62
33
|
onTestCaseStart(test, info) {
|
|
@@ -69,17 +40,10 @@ export default class DescryJestReporter {
|
|
|
69
40
|
});
|
|
70
41
|
}
|
|
71
42
|
onTestCaseResult(test, result) {
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
// `.skip`'d test produces no event from this reporter at all. That is
|
|
77
|
-
// Jest's own coverage limit, not this reporter declining to look: it
|
|
78
|
-
// is why `traceCoverage().notRun` is a floor rather than a total for
|
|
79
|
-
// Jest, and why the tests assert a bound rather than an equality.
|
|
80
|
-
//
|
|
81
|
-
// The translator turns these into `TEST_SKIPPED` (RT-124) — its own
|
|
82
|
-
// event, carrying this location and qualified name, not a counter.
|
|
43
|
+
// `skipped`/`todo` are not passes. Jest reports `test.todo` with status "todo" but
|
|
44
|
+
// omits `.skip`'d tests from onTestCaseResult entirely (measured) -- Jest's own
|
|
45
|
+
// coverage limit, which is why traceCoverage().notRun is a floor, not a total, for
|
|
46
|
+
// Jest. Translator turns these into TEST_SKIPPED (RT-124).
|
|
83
47
|
write(result.status === "failed" ? "test:fail" : "test:pass", {
|
|
84
48
|
name: result.title,
|
|
85
49
|
qualifiedName: result.fullName,
|
|
@@ -88,18 +52,11 @@ export default class DescryJestReporter {
|
|
|
88
52
|
column: result.location?.column ?? null,
|
|
89
53
|
skip: result.status === "skipped" || result.status === "pending" || result.status === "disabled",
|
|
90
54
|
todo: result.status === "todo",
|
|
91
|
-
// Jest names the one it can report: `todo` is a declared absence.
|
|
92
|
-
// The `skipped`/`pending`/`disabled` statuses are switched-off tests,
|
|
93
|
-
// and a `.skip`'d one never reaches this callback at all (measured),
|
|
94
|
-
// so no value here is a guess about a test Jest declined to describe.
|
|
95
55
|
...(result.status === "todo" ? { skipReason: "not-implemented" } : { skipReason: "disabled" }),
|
|
96
56
|
details: {
|
|
97
57
|
duration_ms: result.duration ?? null,
|
|
98
|
-
// Jest
|
|
99
|
-
//
|
|
100
|
-
// the structured half when the matcher provided one; both are
|
|
101
|
-
// passed through verbatim rather than parsed, because parsing a
|
|
102
|
-
// matcher's prose is exactly what this seam exists to avoid.
|
|
58
|
+
// Jest gives failures as formatted strings, not live Error objects; failureDetails
|
|
59
|
+
// is the structured half when present. Both passed through verbatim, not parsed.
|
|
103
60
|
error: result.status === "failed"
|
|
104
61
|
? { failureType: "test", messages: result.failureMessages, details: result.failureDetails ?? null }
|
|
105
62
|
: null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jest-reporter.js","sourceRoot":"","sources":["../src/jest-reporter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"jest-reporter.js","sourceRoot":"","sources":["../src/jest-reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAoBH,SAAS,KAAK,CAAC,IAAY,EAAE,IAAa;IACxC,kFAAkF;IAClF,yCAAyC;IACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED,oFAAoF;AACpF,sFAAsF;AACtF,oBAAoB;AACpB,KAAK,CAAC,iBAAiB,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AAEzC,MAAM,CAAC,OAAO,OAAO,kBAAkB;IACrC,eAAe,CAAC,IAAc,EAAE,IAA2B;QACzD,KAAK,CAAC,YAAY,EAAE;YAClB,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,aAAa,EAAE,IAAI,CAAC,QAAQ;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB,CAAC,IAAc,EAAE,MAA0B;QACzD,mFAAmF;QACnF,gFAAgF;QAChF,mFAAmF;QACnF,2DAA2D;QAC3D,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE;YAC5D,IAAI,EAAE,MAAM,CAAC,KAAK;YAClB,aAAa,EAAE,MAAM,CAAC,QAAQ;YAC9B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,IAAI,IAAI;YACnC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,IAAI;YACvC,IAAI,EAAE,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU;YAChG,IAAI,EAAE,MAAM,CAAC,MAAM,KAAK,MAAM;YAC9B,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAE,EAAE,UAAU,EAAE,iBAAiB,EAAY,CAAC,CAAC,CAAE,EAAE,UAAU,EAAE,UAAU,EAAY,CAAC;YACpH,OAAO,EAAE;gBACP,WAAW,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI;gBACpC,mFAAmF;gBACnF,iFAAiF;gBACjF,KAAK,EACH,MAAM,CAAC,MAAM,KAAK,QAAQ;oBACxB,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,eAAe,EAAE,OAAO,EAAE,MAAM,CAAC,cAAc,IAAI,IAAI,EAAE;oBACnG,CAAC,CAAC,IAAI;aACX;SACF,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -1,40 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Playwright Test's reporter,
|
|
2
|
+
* Playwright Test's reporter, fifth runner on this seam (RT-184).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `swift test --xunit-output` cannot supply them under any flag (RT-136,
|
|
9
|
-
* RT-141). `TestCase.location` is `{file, line, column}` and is always
|
|
10
|
-
* populated. So this profile injects a reporter and nothing else.
|
|
4
|
+
* Only runner measured here supplying source locations with no flag: Jest needs
|
|
5
|
+
* `--testLocationInResults`, Vitest `--includeTaskLocation`, .NET
|
|
6
|
+
* `CollectSourceInformation=true`; `go test` and `swift test --xunit-output` can't
|
|
7
|
+
* supply them at all (RT-136, RT-141). `TestCase.location` is always populated.
|
|
11
8
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* runtime one are not.** `test.annotations` carries `{type: "fixme"}` for
|
|
24
|
-
* `test.fixme()` — unambiguous, a developer switched it off. But
|
|
25
|
-
* `{type: "skip"}` is emitted *identically* for a declared `test.skip(...)`
|
|
26
|
-
* and for a `test.skip(condition)` evaluated inside a running body
|
|
27
|
-
* (measured, both `ann: ["skip"]`). Those are different facts about
|
|
28
|
-
* coverage — switched off versus ran and hit a precondition — and this
|
|
29
|
-
* runner cannot separate them.
|
|
30
|
-
*
|
|
31
|
-
* So `fixme` reports `disabled` and `skip` reports **`unspecified`**. That
|
|
32
|
-
* value now has three independent producers — Vitest (RT-129), .NET's
|
|
33
|
-
* `TestOutcome.Skipped` (Lane A's RT-099) and this — each arriving because
|
|
34
|
-
* a runner collapses two facts rather than because the vocabulary lacked a
|
|
35
|
-
* word. Reading `disabled` off an annotation *named* skip would have been
|
|
36
|
-
* the plausible mistake here, and it would state that a developer turned
|
|
37
|
-
* off a test that ran real code.
|
|
9
|
+
* Two shapes no other runner here has:
|
|
10
|
+
* 1. A test can declare its expected outcome (`test.fail()` → `status: "failed"`,
|
|
11
|
+
* `expectedStatus: "failed"`) — mapping status alone would report a working,
|
|
12
|
+
* deliberately-failing test as a problem. Rule is a comparison: outcome matched
|
|
13
|
+
* the declaration, or it didn't.
|
|
14
|
+
* 2. `fixme` and `skip` annotations are distinguishable, but a declared `test.skip()`
|
|
15
|
+
* and a runtime `test.skip(condition)` both emit `{type: "skip"}` identically
|
|
16
|
+
* (measured) — this runner can't tell "switched off" from "ran and hit a
|
|
17
|
+
* precondition". So `fixme` reports `disabled`, `skip` reports `unspecified`
|
|
18
|
+
* (joining Vitest's RT-129 and .NET's RT-099 as independent producers of the
|
|
19
|
+
* same value, each from a runner collapsing the same two facts).
|
|
38
20
|
*/
|
|
39
21
|
interface PlaywrightLocation {
|
|
40
22
|
readonly file: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright-reporter.d.ts","sourceRoot":"","sources":["../src/playwright-reporter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"playwright-reporter.d.ts","sourceRoot":"","sources":["../src/playwright-reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,eAAe;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,UAAU,gBAAgB;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC;CACrC;AAwBD,MAAM,CAAC,OAAO,OAAO,wBAAwB;IAC3C,SAAS,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI;CAsBpE"}
|
|
@@ -1,56 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Playwright Test's reporter,
|
|
2
|
+
* Playwright Test's reporter, fifth runner on this seam (RT-184).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `swift test --xunit-output` cannot supply them under any flag (RT-136,
|
|
9
|
-
* RT-141). `TestCase.location` is `{file, line, column}` and is always
|
|
10
|
-
* populated. So this profile injects a reporter and nothing else.
|
|
4
|
+
* Only runner measured here supplying source locations with no flag: Jest needs
|
|
5
|
+
* `--testLocationInResults`, Vitest `--includeTaskLocation`, .NET
|
|
6
|
+
* `CollectSourceInformation=true`; `go test` and `swift test --xunit-output` can't
|
|
7
|
+
* supply them at all (RT-136, RT-141). `TestCase.location` is always populated.
|
|
11
8
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* runtime one are not.** `test.annotations` carries `{type: "fixme"}` for
|
|
24
|
-
* `test.fixme()` — unambiguous, a developer switched it off. But
|
|
25
|
-
* `{type: "skip"}` is emitted *identically* for a declared `test.skip(...)`
|
|
26
|
-
* and for a `test.skip(condition)` evaluated inside a running body
|
|
27
|
-
* (measured, both `ann: ["skip"]`). Those are different facts about
|
|
28
|
-
* coverage — switched off versus ran and hit a precondition — and this
|
|
29
|
-
* runner cannot separate them.
|
|
30
|
-
*
|
|
31
|
-
* So `fixme` reports `disabled` and `skip` reports **`unspecified`**. That
|
|
32
|
-
* value now has three independent producers — Vitest (RT-129), .NET's
|
|
33
|
-
* `TestOutcome.Skipped` (Lane A's RT-099) and this — each arriving because
|
|
34
|
-
* a runner collapses two facts rather than because the vocabulary lacked a
|
|
35
|
-
* word. Reading `disabled` off an annotation *named* skip would have been
|
|
36
|
-
* the plausible mistake here, and it would state that a developer turned
|
|
37
|
-
* off a test that ran real code.
|
|
9
|
+
* Two shapes no other runner here has:
|
|
10
|
+
* 1. A test can declare its expected outcome (`test.fail()` → `status: "failed"`,
|
|
11
|
+
* `expectedStatus: "failed"`) — mapping status alone would report a working,
|
|
12
|
+
* deliberately-failing test as a problem. Rule is a comparison: outcome matched
|
|
13
|
+
* the declaration, or it didn't.
|
|
14
|
+
* 2. `fixme` and `skip` annotations are distinguishable, but a declared `test.skip()`
|
|
15
|
+
* and a runtime `test.skip(condition)` both emit `{type: "skip"}` identically
|
|
16
|
+
* (measured) — this runner can't tell "switched off" from "ran and hit a
|
|
17
|
+
* precondition". So `fixme` reports `disabled`, `skip` reports `unspecified`
|
|
18
|
+
* (joining Vitest's RT-129 and .NET's RT-099 as independent producers of the
|
|
19
|
+
* same value, each from a runner collapsing the same two facts).
|
|
38
20
|
*/
|
|
39
21
|
const ENVELOPE_VERSION = 1;
|
|
40
22
|
function write(type, data) {
|
|
41
23
|
process.stdout.write(JSON.stringify({ type, data }) + "\n");
|
|
42
24
|
}
|
|
43
25
|
write("descry:envelope", { version: ENVELOPE_VERSION });
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
* `titlePath()` returns `["", "invoices.spec.js", "invoice deletion", "runs
|
|
48
|
-
* normally"]` — the project name (empty unless projects are configured) and
|
|
49
|
-
* the file title sit in front of it. Slicing a fixed number of entries off
|
|
50
|
-
* would silently take the first `describe` instead once a project is named.
|
|
51
|
-
* `suite.type` is Playwright's own discriminator (`root`/`project`/`file`/
|
|
52
|
-
* `describe`, measured), so the walk stops on a type rather than a count.
|
|
53
|
-
*/
|
|
26
|
+
// The describe() chain only. `titlePath()` includes project/file names ahead of it
|
|
27
|
+
// (e.g. `["", "invoices.spec.js", ...]`), so a fixed-count slice would break once a
|
|
28
|
+
// project is named -- walk stops on `suite.type === "describe"` instead.
|
|
54
29
|
function qualify(test) {
|
|
55
30
|
const groups = [];
|
|
56
31
|
for (let suite = test.parent; suite !== undefined; suite = suite.parent) {
|
|
@@ -66,9 +41,7 @@ function skipReasonOf(test) {
|
|
|
66
41
|
export default class DescryPlaywrightReporter {
|
|
67
42
|
onTestEnd(test, result) {
|
|
68
43
|
const skipped = result.status === "skipped";
|
|
69
|
-
//
|
|
70
|
-
// expected outcome, and a run that matches its declaration is not a
|
|
71
|
-
// problem to report.
|
|
44
|
+
// matches its declared expectedStatus (e.g. test.fail()) -> not a problem to report
|
|
72
45
|
const asDeclared = result.status === test.expectedStatus;
|
|
73
46
|
write(skipped || asDeclared ? "test:pass" : "test:fail", {
|
|
74
47
|
name: test.title,
|
|
@@ -81,10 +54,8 @@ export default class DescryPlaywrightReporter {
|
|
|
81
54
|
...(skipped ? { skipReason: skipReasonOf(test) } : {}),
|
|
82
55
|
details: {
|
|
83
56
|
duration_ms: result.duration,
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
// and a matcher's `snippet`, and copying named fields would discard
|
|
87
|
-
// whichever ones this code did not think to name (RT-123).
|
|
57
|
+
// passed through verbatim, like Vitest's: copying named fields would discard
|
|
58
|
+
// whichever ones weren't named (RT-123)
|
|
88
59
|
error: asDeclared || skipped ? null : { failureType: "test", errors: result.errors },
|
|
89
60
|
},
|
|
90
61
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright-reporter.js","sourceRoot":"","sources":["../src/playwright-reporter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"playwright-reporter.js","sourceRoot":"","sources":["../src/playwright-reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,gBAAgB,GAAG,CAAC,CAAC;AA4B3B,SAAS,KAAK,CAAC,IAAY,EAAE,IAAa;IACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED,KAAK,CAAC,iBAAiB,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC;AAExD,mFAAmF;AACnF,oFAAoF;AACpF,yEAAyE;AACzE,SAAS,OAAO,CAAC,IAAwB;IACvC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,KAAK,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACxE,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,MAAM;QACrC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,YAAY,CAAC,IAAwB;IAC5C,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC;AACvF,CAAC;AAED,MAAM,CAAC,OAAO,OAAO,wBAAwB;IAC3C,SAAS,CAAC,IAAwB,EAAE,MAAwB;QAC1D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC;QAC5C,oFAAoF;QACpF,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,cAAc,CAAC;QAEzD,KAAK,CAAC,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE;YACvD,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC;YAC5B,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;YACxB,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;YACxB,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM;YAC5B,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,KAAK;YACX,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtD,OAAO,EAAE;gBACP,WAAW,EAAE,MAAM,CAAC,QAAQ;gBAC5B,6EAA6E;gBAC7E,wCAAwC;gBACxC,KAAK,EAAE,UAAU,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;aACrF;SACF,CAAC,CAAC;IACL,CAAC;CACF"}
|
package/dist/reporter.d.ts
CHANGED
|
@@ -1,24 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* `node:test` custom reporter (Node's own reporter API, `--test-reporter=`), never TAP:
|
|
3
|
+
* Node's object stream (`test:start`/`test:pass`/`test:fail` with real `error` fields)
|
|
4
|
+
* already gives structured data, so we turn it into one JSON value per line on stdout
|
|
5
|
+
* for `test-runner-collector.ts` to `JSON.parse` — no text scraping (RT-072).
|
|
4
6
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Node's own reporter stream already hands over as real objects —
|
|
9
|
-
* `test:start` / `test:pass` / `test:fail`, each with `name`, `file`,
|
|
10
|
-
* `line`, `column`, and for a failure the real `error` (assertion message,
|
|
11
|
-
* `code`, `cause`), never printed prose to re-parse. This reporter's only
|
|
12
|
-
* job is turning that object stream into one JSON value per line on
|
|
13
|
-
* stdout, so `test-runner-collector.ts` can `JSON.parse` each line instead
|
|
14
|
-
* of pattern-matching text — the same reason RT-072's own benchmark lesson
|
|
15
|
-
* exists ("scraping prose measures the prose").
|
|
16
|
-
*
|
|
17
|
-
* Loaded as a standalone file by a *spawned* `node --test` process, whose
|
|
18
|
-
* own cwd may be anywhere — `test-runner-collector.ts` references this
|
|
19
|
-
* module's compiled path absolutely (`new URL("./reporter.js",
|
|
20
|
-
* import.meta.url)`), never by bare specifier, so it resolves regardless of
|
|
21
|
-
* the target application's own `node_modules`.
|
|
7
|
+
* Loaded by a spawned `node --test` process with an arbitrary cwd, so
|
|
8
|
+
* `test-runner-collector.ts` resolves this module by absolute compiled path
|
|
9
|
+
* (`new URL("./reporter.js", import.meta.url)`), never a bare specifier.
|
|
22
10
|
*/
|
|
23
11
|
interface ReporterEvent {
|
|
24
12
|
readonly type: string;
|
package/dist/reporter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,UAAU,aAAa;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACpH;AAkBD,wBAA+B,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAY1G"}
|
package/dist/reporter.js
CHANGED
|
@@ -1,54 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* `node:test` custom reporter (Node's own reporter API, `--test-reporter=`), never TAP:
|
|
3
|
+
* Node's object stream (`test:start`/`test:pass`/`test:fail` with real `error` fields)
|
|
4
|
+
* already gives structured data, so we turn it into one JSON value per line on stdout
|
|
5
|
+
* for `test-runner-collector.ts` to `JSON.parse` — no text scraping (RT-072).
|
|
4
6
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Node's own reporter stream already hands over as real objects —
|
|
9
|
-
* `test:start` / `test:pass` / `test:fail`, each with `name`, `file`,
|
|
10
|
-
* `line`, `column`, and for a failure the real `error` (assertion message,
|
|
11
|
-
* `code`, `cause`), never printed prose to re-parse. This reporter's only
|
|
12
|
-
* job is turning that object stream into one JSON value per line on
|
|
13
|
-
* stdout, so `test-runner-collector.ts` can `JSON.parse` each line instead
|
|
14
|
-
* of pattern-matching text — the same reason RT-072's own benchmark lesson
|
|
15
|
-
* exists ("scraping prose measures the prose").
|
|
16
|
-
*
|
|
17
|
-
* Loaded as a standalone file by a *spawned* `node --test` process, whose
|
|
18
|
-
* own cwd may be anywhere — `test-runner-collector.ts` references this
|
|
19
|
-
* module's compiled path absolutely (`new URL("./reporter.js",
|
|
20
|
-
* import.meta.url)`), never by bare specifier, so it resolves regardless of
|
|
21
|
-
* the target application's own `node_modules`.
|
|
22
|
-
*/
|
|
23
|
-
/**
|
|
24
|
-
* **`describe()` blocks emit their own `test:pass`, and node:test says so
|
|
25
|
-
* itself** — `data.details.type` is `"suite"` for a container and `"test"`
|
|
26
|
-
* for a real test case (measured; the field's presence is the
|
|
27
|
-
* discriminator, not a heuristic on nesting or naming).
|
|
28
|
-
*
|
|
29
|
-
* That distinction has to survive into the envelope, because it is
|
|
30
|
-
* node:test-specific and Jest's and Vitest's reporters never see a
|
|
31
|
-
* container at all — their per-test callbacks only fire for test cases. So
|
|
32
|
-
* the flag is set here, where the runner-specific knowledge is, and the
|
|
33
|
-
* translator applies one runner-agnostic rule to it.
|
|
34
|
-
*
|
|
35
|
-
* The event itself is still forwarded whole: a suite's `test:fail` is a
|
|
36
|
-
* real failure (a `before`/`after` hook threw) and dropping it here would
|
|
37
|
-
* lose the only signal that a whole block never ran. Which of the two the
|
|
38
|
-
* translator emits is its decision, not this reporter's.
|
|
39
|
-
*/
|
|
40
|
-
/**
|
|
41
|
-
* **node:test tells `skip` and `todo` apart, and RT-124 threw that away.**
|
|
42
|
-
* Both became one `TEST_SKIPPED` with no way to recover which — "switched
|
|
43
|
-
* off" and "never written" are different facts about coverage, and the
|
|
44
|
-
* distinction was dropped silently by the change whose subject was not
|
|
45
|
-
* dropping distinctions silently. `skipReason` is set here rather than
|
|
46
|
-
* derived in the translator because only a reporter knows what its runner
|
|
47
|
-
* can distinguish (RT-129).
|
|
48
|
-
*
|
|
49
|
-
* `todo` wins when both flags are set: `test.todo()` is the stronger claim
|
|
50
|
-
* (there is nothing to run) and node marks a todo as skipped as well.
|
|
7
|
+
* Loaded by a spawned `node --test` process with an arbitrary cwd, so
|
|
8
|
+
* `test-runner-collector.ts` resolves this module by absolute compiled path
|
|
9
|
+
* (`new URL("./reporter.js", import.meta.url)`), never a bare specifier.
|
|
51
10
|
*/
|
|
11
|
+
// `describe()` blocks also emit `test:pass`; `data.details.type` is "suite" vs "test"
|
|
12
|
+
// (measured discriminator, not a nesting/naming heuristic). node:test-specific — Jest/Vitest
|
|
13
|
+
// reporters never see a container — so the flag is set here and applied runner-agnostically
|
|
14
|
+
// by the translator. Event still forwarded whole: a suite's `test:fail` means a hook threw,
|
|
15
|
+
// the only signal a whole block never ran.
|
|
16
|
+
//
|
|
17
|
+
// node:test distinguishes `skip` vs `todo`; RT-124 collapsed both into one `TEST_SKIPPED`,
|
|
18
|
+
// losing "switched off" vs "never written". `skipReason` is set here (RT-129) since only the
|
|
19
|
+
// reporter knows what its runner can distinguish. `todo` wins when both are set — it's the
|
|
20
|
+
// stronger claim (nothing to run), and node also marks todos as skipped.
|
|
52
21
|
function skipReasonOf(data) {
|
|
53
22
|
if (data?.todo === true)
|
|
54
23
|
return "not-implemented";
|
|
@@ -57,10 +26,7 @@ function skipReasonOf(data) {
|
|
|
57
26
|
return undefined;
|
|
58
27
|
}
|
|
59
28
|
export default async function* ndjsonReporter(source) {
|
|
60
|
-
//
|
|
61
|
-
// reporter is a stream transform: its yielded values *are* the output, so
|
|
62
|
-
// a `process.stdout.write` here would race the stream it is supposed to
|
|
63
|
-
// precede. Yielding first is the same guarantee by construction (RT-130).
|
|
29
|
+
// Yielded first, by construction, so it precedes the stream it announces (RT-130).
|
|
64
30
|
yield JSON.stringify({ type: "descry:envelope", data: { version: 1 } }) + "\n";
|
|
65
31
|
for await (const event of source) {
|
|
66
32
|
const isSuite = event.data?.details?.type === "suite";
|
package/dist/reporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,sFAAsF;AACtF,6FAA6F;AAC7F,4FAA4F;AAC5F,4FAA4F;AAC5F,2CAA2C;AAC3C,EAAE;AACF,2FAA2F;AAC3F,6FAA6F;AAC7F,2FAA2F;AAC3F,yEAAyE;AACzE,SAAS,YAAY,CAAC,IAA2B;IAC/C,IAAI,IAAI,EAAE,IAAI,KAAK,IAAI;QAAE,OAAO,iBAAiB,CAAC;IAClD,IAAI,IAAI,EAAE,IAAI,KAAK,IAAI;QAAE,OAAO,UAAU,CAAC;IAC3C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,cAAc,CAAC,MAAoC;IAChF,mFAAmF;IACnF,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;IAC/E,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,OAAO,CAAC;QACtD,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,IAAI,GACR,OAAO,IAAI,UAAU,KAAK,SAAS;YACjC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;YAC/G,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;QACjB,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IAChF,CAAC;AACH,CAAC"}
|