@vitest-agent/reporter 2.2.4 → 3.0.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/defaultReporter.js +102 -14
- package/index.d.ts +75 -4
- package/index.js +1 -1
- package/package.json +6 -6
package/defaultReporter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { renderGithubLog, toDisplayPath } from "./githubLog.js";
|
|
2
2
|
import { createLiveInk } from "./LiveInkRenderer.js";
|
|
3
|
-
import { countSuiteFailures, isTimeoutError } from "@vitest-agent/sdk";
|
|
3
|
+
import { RUN_REPORT_FILE_SCHEMA_URL, countSuiteFailures, isTimeoutError } from "@vitest-agent/sdk";
|
|
4
4
|
import { classifyOutcome, classifyRunShape, dispatch, dispatcherTable, reduceRenderStateAll, synthesizeFromAgentReport } from "@vitest-agent/ui";
|
|
5
5
|
import { Effect, PubSub } from "effect";
|
|
6
6
|
|
|
@@ -199,28 +199,99 @@ const renderTrendSection = (trendSummary) => {
|
|
|
199
199
|
}
|
|
200
200
|
return lines.join("\n");
|
|
201
201
|
};
|
|
202
|
+
const formatSummaryDuration = (ms) => ms >= 1e3 ? `${(ms / 1e3).toFixed(1)}s` : `${Math.round(ms)}ms`;
|
|
202
203
|
/**
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
204
|
+
* Per-project pass/fail/timeout/skip/duration table — the unconditional
|
|
205
|
+
* half of the summary body.
|
|
206
|
+
*
|
|
207
|
+
* Vitest's own `github-actions` reporter no longer writes these counts
|
|
208
|
+
* to the step summary (its job-summary half is disabled), so this table
|
|
209
|
+
* is the only place a CI reader sees the totals. A multi-project run
|
|
210
|
+
* gets a trailing `Total` row; a single-project run does not, because
|
|
211
|
+
* the row would just repeat the one above it.
|
|
212
|
+
*
|
|
213
|
+
* Every count comes from `summarizeProject`, the same projection the
|
|
214
|
+
* console surfaces render from — so the table cannot disagree with what
|
|
215
|
+
* the terminal printed. That matters most for timeouts:
|
|
216
|
+
* `summarizeProject` folds suite-level (collection/load) failures INTO
|
|
217
|
+
* `failCount` and pulls timed-out tests back OUT of it, reporting them
|
|
218
|
+
* in their own column. Recomputing from `report.summary.failed` here
|
|
219
|
+
* would show a timed-out test as `Failed: 1` while every console surface
|
|
220
|
+
* says `0 failed, 1 timed out`.
|
|
221
|
+
*
|
|
222
|
+
* @internal
|
|
213
223
|
*/
|
|
214
|
-
const
|
|
224
|
+
const renderTotalsSection = (reports) => {
|
|
225
|
+
const rows = reports.map((report) => summarizeProject(report));
|
|
226
|
+
const cells = (name, passed, failed, timedOut, skipped, duration) => `| ${name} | ${passed} | ${failed} | ${timedOut} | ${skipped} | ${formatSummaryDuration(duration)} |`;
|
|
227
|
+
const lines = [
|
|
228
|
+
"### Totals",
|
|
229
|
+
"",
|
|
230
|
+
"| Project | Passed | Failed | Timed out | Skipped | Duration |",
|
|
231
|
+
"| --- | --- | --- | --- | --- | --- |",
|
|
232
|
+
...rows.map((r) => cells(r.name, r.passCount, r.failCount, r.timeoutCount ?? 0, r.skipCount, r.durationMs))
|
|
233
|
+
];
|
|
234
|
+
if (rows.length > 1) {
|
|
235
|
+
const total = rows.reduce((acc, r) => ({
|
|
236
|
+
passed: acc.passed + r.passCount,
|
|
237
|
+
failed: acc.failed + r.failCount,
|
|
238
|
+
timedOut: acc.timedOut + (r.timeoutCount ?? 0),
|
|
239
|
+
skipped: acc.skipped + r.skipCount,
|
|
240
|
+
duration: acc.duration + r.durationMs
|
|
241
|
+
}), {
|
|
242
|
+
passed: 0,
|
|
243
|
+
failed: 0,
|
|
244
|
+
timedOut: 0,
|
|
245
|
+
skipped: 0,
|
|
246
|
+
duration: 0
|
|
247
|
+
});
|
|
248
|
+
lines.push(cells("**Total**", total.passed, total.failed, total.timedOut, total.skipped, total.duration));
|
|
249
|
+
}
|
|
250
|
+
return lines.join("\n");
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Assemble the vitest-agent markdown body shared by the GitHub step
|
|
254
|
+
* summary and the `summary.md` report file: a `## vitest-agent` heading,
|
|
255
|
+
* the always-present per-project totals table, then whichever of the
|
|
256
|
+
* classification, coverage, and trend sections have content.
|
|
257
|
+
*
|
|
258
|
+
* Always returns markdown. An all-green run still gets a body — with
|
|
259
|
+
* Vitest's own job summary disabled, returning `null` here left the step
|
|
260
|
+
* summary blank on every passing CI run and wrote no `summary.md` at
|
|
261
|
+
* all.
|
|
262
|
+
*
|
|
263
|
+
* @internal
|
|
264
|
+
*/
|
|
265
|
+
const buildSummaryMarkdown = (input) => {
|
|
215
266
|
const sections = [
|
|
216
267
|
renderClassificationsSection(input.classifications),
|
|
217
268
|
renderCoverageSection(input.reports),
|
|
218
269
|
renderTrendSection(input.trendSummary)
|
|
219
270
|
].filter((section) => section !== null);
|
|
220
|
-
|
|
271
|
+
return [
|
|
272
|
+
"## vitest-agent",
|
|
273
|
+
renderTotalsSection(input.reports),
|
|
274
|
+
...sections
|
|
275
|
+
].join("\n\n");
|
|
276
|
+
};
|
|
277
|
+
/**
|
|
278
|
+
* Builds the vitest-agent GitHub step-summary payload — ONE `RenderedOutput`
|
|
279
|
+
* for the whole run: the per-project totals table, plus test
|
|
280
|
+
* classifications (new-failure / persistent / flaky / recovered),
|
|
281
|
+
* coverage-target shortfalls, and the coverage trend when those have
|
|
282
|
+
* content.
|
|
283
|
+
*
|
|
284
|
+
* The totals used to be omitted on the theory that Vitest's own
|
|
285
|
+
* `github-actions` reporter already wrote pass/fail/skip counts to the
|
|
286
|
+
* same `$GITHUB_STEP_SUMMARY` file. That is no longer true — its
|
|
287
|
+
* job-summary half is disabled — so this block is the only summary a CI
|
|
288
|
+
* reader gets, and it is always emitted. A green run gets a totals table
|
|
289
|
+
* rather than nothing at all.
|
|
290
|
+
*/
|
|
291
|
+
const renderGithubSummary = (input) => {
|
|
221
292
|
return [{
|
|
222
293
|
target: "github-summary",
|
|
223
|
-
content: `\n${
|
|
294
|
+
content: `\n${buildSummaryMarkdown(input)}\n`,
|
|
224
295
|
contentType: "text/markdown"
|
|
225
296
|
}];
|
|
226
297
|
};
|
|
@@ -287,6 +358,23 @@ const DefaultVitestAgentReporter = (kit) => {
|
|
|
287
358
|
out.push(...renderGithubSummary(input));
|
|
288
359
|
out.push(renderGithubLog(input, renderKit));
|
|
289
360
|
}
|
|
361
|
+
out.push({
|
|
362
|
+
target: "report",
|
|
363
|
+
filename: "run.json",
|
|
364
|
+
contentType: "application/json",
|
|
365
|
+
content: `${JSON.stringify({
|
|
366
|
+
$schema: RUN_REPORT_FILE_SCHEMA_URL,
|
|
367
|
+
schemaVersion: 1,
|
|
368
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
369
|
+
reports: input.reports
|
|
370
|
+
}, null, 2)}\n`
|
|
371
|
+
});
|
|
372
|
+
out.push({
|
|
373
|
+
target: "report",
|
|
374
|
+
filename: "summary.md",
|
|
375
|
+
contentType: "text/markdown",
|
|
376
|
+
content: `${buildSummaryMarkdown(input)}\n`
|
|
377
|
+
});
|
|
290
378
|
return out;
|
|
291
379
|
} };
|
|
292
380
|
};
|
package/index.d.ts
CHANGED
|
@@ -365,6 +365,12 @@ declare const AgentReport: Schema.Struct<{
|
|
|
365
365
|
readonly functions: Schema.optional<Schema.Number>;
|
|
366
366
|
readonly branches: Schema.optional<Schema.Number>;
|
|
367
367
|
readonly statements: Schema.optional<Schema.Number>;
|
|
368
|
+
readonly perFile: Schema.optionalKey<Schema.Union<readonly [Schema.Boolean, Schema.Struct<{
|
|
369
|
+
readonly lines: Schema.optional<Schema.Number>;
|
|
370
|
+
readonly functions: Schema.optional<Schema.Number>;
|
|
371
|
+
readonly branches: Schema.optional<Schema.Number>;
|
|
372
|
+
readonly statements: Schema.optional<Schema.Number>;
|
|
373
|
+
}>]>>;
|
|
368
374
|
}>]>>, never>;
|
|
369
375
|
}>;
|
|
370
376
|
readonly targets: Schema.optional<Schema.Struct<{
|
|
@@ -379,6 +385,12 @@ declare const AgentReport: Schema.Struct<{
|
|
|
379
385
|
readonly functions: Schema.optional<Schema.Number>;
|
|
380
386
|
readonly branches: Schema.optional<Schema.Number>;
|
|
381
387
|
readonly statements: Schema.optional<Schema.Number>;
|
|
388
|
+
readonly perFile: Schema.optionalKey<Schema.Union<readonly [Schema.Boolean, Schema.Struct<{
|
|
389
|
+
readonly lines: Schema.optional<Schema.Number>;
|
|
390
|
+
readonly functions: Schema.optional<Schema.Number>;
|
|
391
|
+
readonly branches: Schema.optional<Schema.Number>;
|
|
392
|
+
readonly statements: Schema.optional<Schema.Number>;
|
|
393
|
+
}>]>>;
|
|
382
394
|
}>]>>, never>;
|
|
383
395
|
}>>;
|
|
384
396
|
readonly baselines: Schema.optional<Schema.Struct<{
|
|
@@ -393,6 +405,12 @@ declare const AgentReport: Schema.Struct<{
|
|
|
393
405
|
readonly functions: Schema.optional<Schema.Number>;
|
|
394
406
|
readonly branches: Schema.optional<Schema.Number>;
|
|
395
407
|
readonly statements: Schema.optional<Schema.Number>;
|
|
408
|
+
readonly perFile: Schema.optionalKey<Schema.Union<readonly [Schema.Boolean, Schema.Struct<{
|
|
409
|
+
readonly lines: Schema.optional<Schema.Number>;
|
|
410
|
+
readonly functions: Schema.optional<Schema.Number>;
|
|
411
|
+
readonly branches: Schema.optional<Schema.Number>;
|
|
412
|
+
readonly statements: Schema.optional<Schema.Number>;
|
|
413
|
+
}>]>>;
|
|
396
414
|
}>]>>, never>;
|
|
397
415
|
}>>;
|
|
398
416
|
readonly scoped: Schema.withDecodingDefaultKey<Schema.Boolean, never>;
|
|
@@ -489,12 +507,29 @@ declare const DetailLevel: Schema.Literals<readonly ["minimal", "neutral", "stan
|
|
|
489
507
|
type DetailLevel = typeof DetailLevel.Type;
|
|
490
508
|
//#endregion
|
|
491
509
|
//#region src/formatters/types.d.ts
|
|
492
|
-
/**
|
|
493
|
-
|
|
510
|
+
/**
|
|
511
|
+
* One unit of rendered reporter output, tagged by where it goes.
|
|
512
|
+
*
|
|
513
|
+
* `stdout` writes to the process stdout stream, `github-summary`
|
|
514
|
+
* appends to the GitHub Actions step-summary file, and `file` is
|
|
515
|
+
* reserved for reporters that embed their own destination path.
|
|
516
|
+
*
|
|
517
|
+
* `report` writes `filename` into `.vitest/<scope>/` through Vitest 5's
|
|
518
|
+
* `createReport`. The plugin drops these when reporting is disabled,
|
|
519
|
+
* exactly as it drops `github-summary` outside GitHub Actions.
|
|
520
|
+
*
|
|
521
|
+
* @public
|
|
522
|
+
*/
|
|
523
|
+
type RenderedOutput = {
|
|
494
524
|
readonly target: "stdout" | "file" | "github-summary";
|
|
495
525
|
readonly content: string;
|
|
496
526
|
readonly contentType: string;
|
|
497
|
-
}
|
|
527
|
+
} | {
|
|
528
|
+
readonly target: "report";
|
|
529
|
+
readonly filename: string;
|
|
530
|
+
readonly content: string;
|
|
531
|
+
readonly contentType: string;
|
|
532
|
+
};
|
|
498
533
|
/**
|
|
499
534
|
* The reducer projects this union into `RenderState`. Renderers
|
|
500
535
|
* never read the raw event stream — they read the projected state.
|
|
@@ -588,11 +623,36 @@ declare const RunEvent: Schema.Union<readonly [Schema.TaggedStruct<"RunStarted",
|
|
|
588
623
|
readonly testName: Schema.String;
|
|
589
624
|
readonly suitePath: Schema.$Array<Schema.String>;
|
|
590
625
|
readonly annotation: Schema.String;
|
|
626
|
+
readonly annotationType: Schema.String;
|
|
627
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
628
|
+
readonly file: Schema.String;
|
|
629
|
+
readonly line: Schema.Number;
|
|
630
|
+
readonly column: Schema.Number;
|
|
631
|
+
}>>;
|
|
632
|
+
readonly attachments: Schema.$Array<Schema.Struct<{
|
|
633
|
+
readonly contentType: Schema.optional<Schema.String>;
|
|
634
|
+
readonly path: Schema.optional<Schema.String>;
|
|
635
|
+
readonly body: Schema.optional<Schema.String>;
|
|
636
|
+
readonly bodyEncoding: Schema.optional<Schema.Literals<readonly ["base64", "utf-8"]>>;
|
|
637
|
+
readonly byteSize: Schema.Number;
|
|
638
|
+
}>>;
|
|
591
639
|
}>, Schema.TaggedStruct<"TestArtifactRecorded", {
|
|
592
640
|
readonly modulePath: Schema.String;
|
|
593
641
|
readonly testName: Schema.String;
|
|
594
642
|
readonly suitePath: Schema.$Array<Schema.String>;
|
|
595
643
|
readonly artifact: Schema.String;
|
|
644
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
645
|
+
readonly file: Schema.String;
|
|
646
|
+
readonly line: Schema.Number;
|
|
647
|
+
readonly column: Schema.Number;
|
|
648
|
+
}>>;
|
|
649
|
+
readonly attachments: Schema.$Array<Schema.Struct<{
|
|
650
|
+
readonly contentType: Schema.optional<Schema.String>;
|
|
651
|
+
readonly path: Schema.optional<Schema.String>;
|
|
652
|
+
readonly body: Schema.optional<Schema.String>;
|
|
653
|
+
readonly bodyEncoding: Schema.optional<Schema.Literals<readonly ["base64", "utf-8"]>>;
|
|
654
|
+
readonly byteSize: Schema.Number;
|
|
655
|
+
}>>;
|
|
596
656
|
}>, Schema.TaggedStruct<"WatcherReady", {}>, Schema.TaggedStruct<"WatcherRerun", {
|
|
597
657
|
readonly triggerFiles: Schema.$Array<Schema.String>;
|
|
598
658
|
readonly reason: Schema.optional<Schema.String>;
|
|
@@ -681,12 +741,23 @@ declare const ResolvedThresholds: Schema.Struct<{
|
|
|
681
741
|
readonly branches: Schema.optional<Schema.Number>;
|
|
682
742
|
readonly statements: Schema.optional<Schema.Number>;
|
|
683
743
|
}>;
|
|
684
|
-
readonly perFile: Schema.withDecodingDefaultKey<Schema.Boolean,
|
|
744
|
+
readonly perFile: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Boolean, Schema.Struct<{
|
|
745
|
+
readonly lines: Schema.optional<Schema.Number>;
|
|
746
|
+
readonly functions: Schema.optional<Schema.Number>;
|
|
747
|
+
readonly branches: Schema.optional<Schema.Number>;
|
|
748
|
+
readonly statements: Schema.optional<Schema.Number>;
|
|
749
|
+
}>]>, never>;
|
|
685
750
|
readonly patterns: Schema.withDecodingDefaultKey<Schema.$Array<Schema.Tuple<readonly [Schema.String, Schema.Struct<{
|
|
686
751
|
readonly lines: Schema.optional<Schema.Number>;
|
|
687
752
|
readonly functions: Schema.optional<Schema.Number>;
|
|
688
753
|
readonly branches: Schema.optional<Schema.Number>;
|
|
689
754
|
readonly statements: Schema.optional<Schema.Number>;
|
|
755
|
+
readonly perFile: Schema.optionalKey<Schema.Union<readonly [Schema.Boolean, Schema.Struct<{
|
|
756
|
+
readonly lines: Schema.optional<Schema.Number>;
|
|
757
|
+
readonly functions: Schema.optional<Schema.Number>;
|
|
758
|
+
readonly branches: Schema.optional<Schema.Number>;
|
|
759
|
+
readonly statements: Schema.optional<Schema.Number>;
|
|
760
|
+
}>]>>;
|
|
690
761
|
}>]>>, never>;
|
|
691
762
|
}>;
|
|
692
763
|
/** @public */
|
package/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { DefaultVitestAgentReporter, buildDispatchInputs, renderAgentStringForRe
|
|
|
9
9
|
*
|
|
10
10
|
* @public
|
|
11
11
|
*/
|
|
12
|
-
const CURRENT_REPORTER_VERSION = "
|
|
12
|
+
const CURRENT_REPORTER_VERSION = "3.0.1";
|
|
13
13
|
|
|
14
14
|
//#endregion
|
|
15
15
|
export { CURRENT_REPORTER_VERSION, DefaultVitestAgentReporter, createLiveInk as _createLiveInk, buildDispatchInputs, renderAgentStringForReport, renderHumanStringForReport, resolveCellOptions };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest-agent/reporter",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Named VitestAgentReporterFactory implementations for the vitest-agent ecosystem.",
|
|
6
6
|
"keywords": [
|
|
@@ -41,16 +41,16 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
43
43
|
"@effect/sql-sqlite-node": "4.0.0-rc.112",
|
|
44
|
-
"@vitest-agent/sdk": "
|
|
45
|
-
"@vitest-agent/ui": "2.
|
|
44
|
+
"@vitest-agent/sdk": "3.1.0",
|
|
45
|
+
"@vitest-agent/ui": "2.4.1",
|
|
46
46
|
"effect": "4.0.0-rc.112",
|
|
47
47
|
"ink": "^7.1.1",
|
|
48
48
|
"react": "^19.2.8"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
-
"@vitest/coverage-istanbul": "^
|
|
52
|
-
"@vitest/coverage-v8": "^
|
|
53
|
-
"vitest": "^
|
|
51
|
+
"@vitest/coverage-istanbul": "^5.0.0",
|
|
52
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
53
|
+
"vitest": "^5.0.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"@vitest/coverage-istanbul": {
|