@quenty/cli-output-helpers 1.17.2 → 1.18.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/outputHelper.d.ts +11 -0
  3. package/dist/outputHelper.d.ts.map +1 -1
  4. package/dist/outputHelper.js +18 -0
  5. package/dist/outputHelper.js.map +1 -1
  6. package/dist/reporting/aggregated-batch-reporter.d.ts +31 -0
  7. package/dist/reporting/aggregated-batch-reporter.d.ts.map +1 -0
  8. package/dist/reporting/aggregated-batch-reporter.js +40 -0
  9. package/dist/reporting/aggregated-batch-reporter.js.map +1 -0
  10. package/dist/reporting/github/formatting.d.ts.map +1 -1
  11. package/dist/reporting/github/formatting.js +37 -32
  12. package/dist/reporting/github/formatting.js.map +1 -1
  13. package/dist/reporting/grouped-reporter.d.ts.map +1 -1
  14. package/dist/reporting/grouped-reporter.js +7 -28
  15. package/dist/reporting/grouped-reporter.js.map +1 -1
  16. package/dist/reporting/index.d.ts +2 -0
  17. package/dist/reporting/index.d.ts.map +1 -1
  18. package/dist/reporting/index.js +2 -0
  19. package/dist/reporting/index.js.map +1 -1
  20. package/dist/reporting/reporter.d.ts +17 -0
  21. package/dist/reporting/reporter.d.ts.map +1 -1
  22. package/dist/reporting/reporter.js.map +1 -1
  23. package/dist/reporting/result-status.d.ts +101 -0
  24. package/dist/reporting/result-status.d.ts.map +1 -0
  25. package/dist/reporting/result-status.js +138 -0
  26. package/dist/reporting/result-status.js.map +1 -0
  27. package/dist/reporting/result-status.test.d.ts +2 -0
  28. package/dist/reporting/result-status.test.d.ts.map +1 -0
  29. package/dist/reporting/result-status.test.js +108 -0
  30. package/dist/reporting/result-status.test.js.map +1 -0
  31. package/dist/reporting/spinner-reporter.d.ts +1 -0
  32. package/dist/reporting/spinner-reporter.d.ts.map +1 -1
  33. package/dist/reporting/spinner-reporter.js +18 -33
  34. package/dist/reporting/spinner-reporter.js.map +1 -1
  35. package/dist/reporting/summary-table-reporter.d.ts +7 -2
  36. package/dist/reporting/summary-table-reporter.d.ts.map +1 -1
  37. package/dist/reporting/summary-table-reporter.js +16 -27
  38. package/dist/reporting/summary-table-reporter.js.map +1 -1
  39. package/package.json +2 -2
  40. package/src/outputHelper.ts +22 -0
  41. package/src/reporting/aggregated-batch-reporter.ts +45 -0
  42. package/src/reporting/github/formatting.ts +52 -41
  43. package/src/reporting/grouped-reporter.ts +20 -42
  44. package/src/reporting/index.ts +13 -0
  45. package/src/reporting/reporter.ts +18 -0
  46. package/src/reporting/result-status.test.ts +149 -0
  47. package/src/reporting/result-status.ts +227 -0
  48. package/src/reporting/spinner-reporter.ts +40 -39
  49. package/src/reporting/summary-table-reporter.ts +29 -36
  50. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,101 @@
1
+ /**
2
+ * One answer to "how did this turn out", for every place that has to say so.
3
+ *
4
+ * A result's state was worked out independently in four places — the summary
5
+ * table, the grouped reporter, the spinner and the PR comment — and each had its
6
+ * own idea of it. "Ran zero tests" was a warning in three of them and invisible
7
+ * in the fourth; the icon was `⚠` in two and `⚠️` in the others; a pass showed
8
+ * its counts in some and not others; and the run-level tallies at the bottom of
9
+ * each were counted separately, so they could disagree with the rows above them.
10
+ *
11
+ * Adding a fifth state made that untenable: a pass whose log output was dropped
12
+ * is still a pass, but not one that should look like every other green row, and
13
+ * teaching five renderers about it one at a time is how the four drifted in the
14
+ * first place.
15
+ *
16
+ * So state is resolved once, here, and the renderers only choose how to draw it.
17
+ */
18
+ import { type JobPhase, type ProgressSummary, type ResultCaveat } from './reporter.js';
19
+ /** How a result should read at a glance. */
20
+ export type ResultSeverity = 'success' | 'warning' | 'failure';
21
+ export { type ResultCaveat } from './reporter.js';
22
+ /**
23
+ * The parts of a result that decide its state.
24
+ *
25
+ * Structural rather than `PackageResult` so a caller holding some other shape —
26
+ * the batch log parser's per-package result, say — can resolve state without
27
+ * first building a reporting type it has no other use for.
28
+ */
29
+ export interface ResultStatusInput {
30
+ success: boolean;
31
+ progressSummary?: ProgressSummary;
32
+ failedPhase?: JobPhase;
33
+ /** Per-result override of the reporter's default failure label. */
34
+ failureLabel?: string;
35
+ /**
36
+ * Caveats the producer knows about and the resolver cannot see. `empty-run`
37
+ * and `no-counts` are derived from the counts themselves and need not be
38
+ * passed; `logs-lost` is a fact about the run that only its parser knows.
39
+ */
40
+ caveats?: ResultCaveat[];
41
+ }
42
+ export interface ResolveResultStatusOptions {
43
+ /** Verdict word for a pass. Default "Passed". */
44
+ successLabel?: string;
45
+ /** Verdict word for a failure. Default "FAILED". */
46
+ failureLabel?: string;
47
+ /**
48
+ * True when this kind of run should have reported test counts, which makes
49
+ * their absence a caveat rather than simply nothing to show.
50
+ */
51
+ expectsTestCounts?: boolean;
52
+ }
53
+ export interface ResultStatus {
54
+ severity: ResultSeverity;
55
+ /** The verdict word alone: "Passed", "FAILED", "Unverified". */
56
+ label: string;
57
+ /** Where it failed, when the failure names a phase. */
58
+ failedPhase?: JobPhase;
59
+ /** Counts or bytes as "(68/68)", or empty when there are none. */
60
+ progress: string;
61
+ /** Everything qualifying this result, in the order they are worth reading. */
62
+ caveats: ResultCaveat[];
63
+ }
64
+ /**
65
+ * Work out how a result should be presented.
66
+ *
67
+ * A failure stays a failure whatever its caveats; a pass carrying any caveat
68
+ * becomes a warning. Caveats are not exclusive — a run can report no counts and
69
+ * have lost its logs — so they are collected rather than ranked, and every
70
+ * renderer shows all of them.
71
+ */
72
+ export declare function resolveResultStatus(result: ResultStatusInput, options?: ResolveResultStatusOptions): ResultStatus;
73
+ /**
74
+ * The status as one line of plain text: "Passed (35/35) - logs lost".
75
+ *
76
+ * No icon, no duration and no color — those differ between a markdown table, a
77
+ * terminal line and a collapsible group header, and are the renderer's to add.
78
+ */
79
+ export declare function formatStatusText(status: ResultStatus): string;
80
+ /**
81
+ * The icon for a severity.
82
+ *
83
+ * `emoji` for markdown, where they render as intended; `ascii` for a terminal
84
+ * line, where a variation-selector emoji is two columns wide and breaks column
85
+ * alignment.
86
+ */
87
+ export declare function statusIcon(severity: ResultSeverity, style: 'emoji' | 'ascii'): string;
88
+ /** Color text by severity, using the shared palette. */
89
+ export declare function colorStatus(text: string, severity: ResultSeverity): string;
90
+ /**
91
+ * Roll up the caveats across a run, for the lines under a summary.
92
+ *
93
+ * Counted off the same statuses the rows were drawn from, so the tally and the
94
+ * rows cannot disagree — which they could when each reporter counted its own.
95
+ */
96
+ export declare function tallyCaveats(statuses: ResultStatus[]): Array<{
97
+ caveat: ResultCaveat;
98
+ count: number;
99
+ message: string;
100
+ }>;
101
+ //# sourceMappingURL=result-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-status.d.ts","sourceRoot":"","sources":["../../src/reporting/result-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAGvB,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE/D,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AA0BlD;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,0BAA0B;IACzC,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,0BAA+B,GACvC,YAAY,CAuCd;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAY7D;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,OAAO,GAAG,OAAO,GACvB,MAAM,CAMR;AAED,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,CAS1E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,YAAY,EAAE,GACvB,KAAK,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBjE"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * One answer to "how did this turn out", for every place that has to say so.
3
+ *
4
+ * A result's state was worked out independently in four places — the summary
5
+ * table, the grouped reporter, the spinner and the PR comment — and each had its
6
+ * own idea of it. "Ran zero tests" was a warning in three of them and invisible
7
+ * in the fourth; the icon was `⚠` in two and `⚠️` in the others; a pass showed
8
+ * its counts in some and not others; and the run-level tallies at the bottom of
9
+ * each were counted separately, so they could disagree with the rows above them.
10
+ *
11
+ * Adding a fifth state made that untenable: a pass whose log output was dropped
12
+ * is still a pass, but not one that should look like every other green row, and
13
+ * teaching five renderers about it one at a time is how the four drifted in the
14
+ * first place.
15
+ *
16
+ * So state is resolved once, here, and the renderers only choose how to draw it.
17
+ */
18
+ import { OutputHelper } from '../outputHelper.js';
19
+ import { formatProgressResult, isEmptyTestRun } from './progress-format.js';
20
+ const CAVEAT_COPY = {
21
+ 'no-counts': {
22
+ label: 'no test counts reported',
23
+ tally: (count) => `${count} package(s) reported no test counts — a pass here proves nothing about whether tests ran`,
24
+ },
25
+ 'logs-lost': {
26
+ label: 'logs lost',
27
+ tally: (count) => `${count} package(s) lost their log output — their counts came back in the run's summary, but nothing could be checked for tracebacks`,
28
+ },
29
+ 'empty-run': {
30
+ label: 'ran 0 tests',
31
+ tally: (count) => `${count} package(s) ran 0 tests — check test discovery`,
32
+ },
33
+ };
34
+ /**
35
+ * Work out how a result should be presented.
36
+ *
37
+ * A failure stays a failure whatever its caveats; a pass carrying any caveat
38
+ * becomes a warning. Caveats are not exclusive — a run can report no counts and
39
+ * have lost its logs — so they are collected rather than ranked, and every
40
+ * renderer shows all of them.
41
+ */
42
+ export function resolveResultStatus(result, options = {}) {
43
+ const caveats = [];
44
+ if ((options.expectsTestCounts ?? false) &&
45
+ result.progressSummary === undefined) {
46
+ caveats.push('no-counts');
47
+ }
48
+ for (const caveat of result.caveats ?? []) {
49
+ if (!caveats.includes(caveat)) {
50
+ caveats.push(caveat);
51
+ }
52
+ }
53
+ if (isEmptyTestRun(result.progressSummary)) {
54
+ caveats.push('empty-run');
55
+ }
56
+ if (!result.success) {
57
+ return {
58
+ severity: 'failure',
59
+ label: result.failureLabel ?? options.failureLabel ?? 'FAILED',
60
+ failedPhase: result.failedPhase,
61
+ progress: formatProgressResult(result.progressSummary),
62
+ caveats,
63
+ };
64
+ }
65
+ // "Unverified" rather than "Passed": with no counts at all, the run's own
66
+ // account of itself never arrived, and calling that a pass is the claim this
67
+ // is here to avoid making.
68
+ const unverified = caveats.includes('no-counts');
69
+ return {
70
+ severity: caveats.length > 0 ? 'warning' : 'success',
71
+ label: unverified ? 'Unverified' : options.successLabel ?? 'Passed',
72
+ progress: unverified ? '' : formatProgressResult(result.progressSummary),
73
+ caveats,
74
+ };
75
+ }
76
+ /**
77
+ * The status as one line of plain text: "Passed (35/35) - logs lost".
78
+ *
79
+ * No icon, no duration and no color — those differ between a markdown table, a
80
+ * terminal line and a collapsible group header, and are the renderer's to add.
81
+ */
82
+ export function formatStatusText(status) {
83
+ const verdict = status.failedPhase
84
+ ? `${status.label} at ${status.failedPhase}`
85
+ : status.label;
86
+ const head = [verdict, status.progress].filter(Boolean).join(' ');
87
+ if (status.caveats.length === 0) {
88
+ return head;
89
+ }
90
+ return `${head} - ${status.caveats
91
+ .map((caveat) => CAVEAT_COPY[caveat].label)
92
+ .join(', ')}`;
93
+ }
94
+ /**
95
+ * The icon for a severity.
96
+ *
97
+ * `emoji` for markdown, where they render as intended; `ascii` for a terminal
98
+ * line, where a variation-selector emoji is two columns wide and breaks column
99
+ * alignment.
100
+ */
101
+ export function statusIcon(severity, style) {
102
+ if (style === 'emoji') {
103
+ return severity === 'failure' ? '❌' : severity === 'warning' ? '⚠️' : '✅';
104
+ }
105
+ return severity === 'failure' ? '✗' : severity === 'warning' ? '⚠' : '✓';
106
+ }
107
+ /** Color text by severity, using the shared palette. */
108
+ export function colorStatus(text, severity) {
109
+ if (severity === 'failure') {
110
+ return OutputHelper.formatError(text);
111
+ }
112
+ if (severity === 'warning') {
113
+ return OutputHelper.formatWarning(text);
114
+ }
115
+ return OutputHelper.formatSuccess(text);
116
+ }
117
+ /**
118
+ * Roll up the caveats across a run, for the lines under a summary.
119
+ *
120
+ * Counted off the same statuses the rows were drawn from, so the tally and the
121
+ * rows cannot disagree — which they could when each reporter counted its own.
122
+ */
123
+ export function tallyCaveats(statuses) {
124
+ const counts = new Map();
125
+ for (const status of statuses) {
126
+ for (const caveat of status.caveats) {
127
+ counts.set(caveat, (counts.get(caveat) ?? 0) + 1);
128
+ }
129
+ }
130
+ const order = ['no-counts', 'logs-lost', 'empty-run'];
131
+ return order
132
+ .filter((caveat) => counts.has(caveat))
133
+ .map((caveat) => {
134
+ const count = counts.get(caveat);
135
+ return { caveat, count, message: CAVEAT_COPY[caveat].tally(count) };
136
+ });
137
+ }
138
+ //# sourceMappingURL=result-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-status.js","sourceRoot":"","sources":["../../src/reporting/result-status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=result-status.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-status.test.d.ts","sourceRoot":"","sources":["../../src/reporting/result-status.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,108 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { formatStatusText, resolveResultStatus, statusIcon, tallyCaveats, } from './result-status.js';
3
+ function counts(passed, total) {
4
+ return {
5
+ success: true,
6
+ progressSummary: {
7
+ kind: 'test-counts',
8
+ passed,
9
+ failed: total - passed,
10
+ total,
11
+ },
12
+ };
13
+ }
14
+ describe('resolveResultStatus', () => {
15
+ it('calls a clean pass a success', () => {
16
+ const status = resolveResultStatus(counts(68, 68));
17
+ expect(status.severity).toBe('success');
18
+ expect(formatStatusText(status)).toBe('Passed (68/68)');
19
+ });
20
+ it('keeps a failure a failure however it is qualified', () => {
21
+ // A caveat narrows what a result proves; it never softens a failure into a
22
+ // warning, or a red row would go amber for having lost its logs.
23
+ const status = resolveResultStatus({
24
+ ...counts(3, 4),
25
+ success: false,
26
+ caveats: ['logs-lost'],
27
+ });
28
+ expect(status.severity).toBe('failure');
29
+ expect(formatStatusText(status)).toBe('FAILED (3/4) - logs lost');
30
+ });
31
+ it('demotes a pass that carries a caveat to a warning', () => {
32
+ const status = resolveResultStatus({
33
+ ...counts(35, 35),
34
+ caveats: ['logs-lost'],
35
+ });
36
+ expect(status.severity).toBe('warning');
37
+ expect(formatStatusText(status)).toBe('Passed (35/35) - logs lost');
38
+ });
39
+ it('flags a pass that ran no tests', () => {
40
+ const status = resolveResultStatus(counts(0, 0));
41
+ expect(status.severity).toBe('warning');
42
+ expect(status.caveats).toEqual(['empty-run']);
43
+ });
44
+ it('calls a pass with no counts unverified, when counts were expected', () => {
45
+ // The claim being avoided: a green row with nothing behind it is
46
+ // indistinguishable from one that tested something.
47
+ const status = resolveResultStatus({ success: true }, { expectsTestCounts: true });
48
+ expect(status.severity).toBe('warning');
49
+ expect(formatStatusText(status)).toBe('Unverified - no test counts reported');
50
+ });
51
+ it('says nothing about missing counts where none were expected', () => {
52
+ // A deploy has no test counts and is not suspect for lacking them.
53
+ const status = resolveResultStatus({ success: true });
54
+ expect(status.severity).toBe('success');
55
+ expect(status.caveats).toEqual([]);
56
+ });
57
+ it('reports every caveat that applies, not just the first', () => {
58
+ const status = resolveResultStatus({ ...counts(0, 0), caveats: ['logs-lost'] }, { expectsTestCounts: true });
59
+ expect(status.caveats).toEqual(['logs-lost', 'empty-run']);
60
+ expect(formatStatusText(status)).toBe('Passed (0/0) - logs lost, ran 0 tests');
61
+ });
62
+ it('names the phase a failure happened in', () => {
63
+ const status = resolveResultStatus({
64
+ success: false,
65
+ failedPhase: 'uploading',
66
+ });
67
+ expect(formatStatusText(status)).toBe('FAILED at uploading');
68
+ });
69
+ it('takes the labels the caller uses for its own kind of run', () => {
70
+ const status = resolveResultStatus({ success: true }, { successLabel: 'Deployed' });
71
+ expect(formatStatusText(status)).toBe('Deployed');
72
+ });
73
+ });
74
+ describe('tallyCaveats', () => {
75
+ it('counts each caveat across a run', () => {
76
+ const statuses = [
77
+ resolveResultStatus({ ...counts(5, 5), caveats: ['logs-lost'] }),
78
+ resolveResultStatus({ ...counts(9, 9), caveats: ['logs-lost'] }),
79
+ resolveResultStatus(counts(0, 0)),
80
+ ];
81
+ expect(tallyCaveats(statuses)).toEqual([
82
+ {
83
+ caveat: 'logs-lost',
84
+ count: 2,
85
+ message: expect.stringContaining('2 package(s) lost their log output'),
86
+ },
87
+ {
88
+ caveat: 'empty-run',
89
+ count: 1,
90
+ message: '1 package(s) ran 0 tests — check test discovery',
91
+ },
92
+ ]);
93
+ });
94
+ it('says nothing when every result is clean', () => {
95
+ expect(tallyCaveats([resolveResultStatus(counts(3, 3))])).toEqual([]);
96
+ });
97
+ });
98
+ describe('statusIcon', () => {
99
+ it('uses emoji for markdown and single-width glyphs for a terminal', () => {
100
+ // A variation-selector emoji is two columns wide, which breaks the aligned
101
+ // status column in the summary table.
102
+ expect(statusIcon('warning', 'emoji')).toBe('⚠️');
103
+ expect(statusIcon('warning', 'ascii')).toBe('⚠');
104
+ expect(statusIcon('success', 'ascii')).toBe('✓');
105
+ expect(statusIcon('failure', 'ascii')).toBe('✗');
106
+ });
107
+ });
108
+ //# sourceMappingURL=result-status.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-status.test.js","sourceRoot":"","sources":["../../src/reporting/result-status.test.ts"],"names":[],"mappings":"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"}
@@ -39,6 +39,7 @@ export declare class SpinnerReporter extends BaseReporter {
39
39
  private _printFailureLogs;
40
40
  private _printAllLogs;
41
41
  private _printResultLogs;
42
+ private _resolve;
42
43
  private _render;
43
44
  }
44
45
  //# sourceMappingURL=spinner-reporter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spinner-reporter.d.ts","sourceRoot":"","sources":["../../src/reporting/spinner-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqC,YAAY,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAO9D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,OAAO,CAAC;IAClB,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyBD;;;;;;;;;;;GAWG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,eAAe,CAAC,CAAiC;IACzD,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,eAAe,CAAc;IACrC,OAAO,CAAC,oBAAoB,CAA0C;IACtE,OAAO,CAAC,oBAAoB,CAA0C;IACtE,OAAO,CAAC,YAAY,CAAS;gBAEjB,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,sBAAsB;IAMlD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoD3B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAkCzC,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,gBAAgB;IA4BxB,OAAO,CAAC,OAAO;CAmFhB"}
1
+ {"version":3,"file":"spinner-reporter.d.ts","sourceRoot":"","sources":["../../src/reporting/spinner-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqC,YAAY,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAS9D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,OAAO,CAAC;IAClB,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyBD;;;;;;;;;;;GAWG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,eAAe,CAAC,CAAiC;IACzD,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,eAAe,CAAc;IACrC,OAAO,CAAC,oBAAoB,CAA0C;IACtE,OAAO,CAAC,oBAAoB,CAA0C;IACtE,OAAO,CAAC,YAAY,CAAS;gBAEjB,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,sBAAsB;IAMlD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoD3B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAkCzC,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,gBAAgB;IA2BxB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,OAAO;CA0EhB"}
@@ -1,7 +1,8 @@
1
1
  import { OutputHelper } from '../outputHelper.js';
2
2
  import { formatDurationMs } from '../cli-utils.js';
3
3
  import { BaseReporter } from './reporter.js';
4
- import { formatProgressInline, formatProgressResult, isEmptyTestRun, } from './progress-format.js';
4
+ import { formatProgressInline } from './progress-format.js';
5
+ import { colorStatus, formatStatusText, resolveResultStatus, statusIcon, } from './result-status.js';
5
6
  const SPINNER_FRAMES = ['◐', '◓', '◑', '◒'];
6
7
  // Wide enough to fit "⬇ Downloading (12.3 MB/12.3 MB)" without bumping the
7
8
  // duration column out of alignment. Bytes progress is the widest case; test
@@ -134,16 +135,9 @@ export class SpinnerReporter extends BaseReporter {
134
135
  }
135
136
  }
136
137
  _printResultLogs(result) {
137
- const icon = result.success
138
- ? OutputHelper.formatSuccess('✓')
139
- : OutputHelper.formatError('✗');
140
- const status = result.success
141
- ? this._options.successLabel ?? 'Passed'
142
- : result.failureLabel ?? this._options.failureLabel ?? 'FAILED';
143
- const formatted = result.success
144
- ? OutputHelper.formatSuccess(status)
145
- : OutputHelper.formatError(status);
146
- console.log(`${icon} ${OutputHelper.formatDim('──')} ${result.packageName} ${OutputHelper.formatDim('──')} ${formatted}`);
138
+ const status = this._resolve(result);
139
+ const icon = colorStatus(statusIcon(status.severity, 'ascii'), status.severity);
140
+ console.log(`${icon} ${OutputHelper.formatDim('──')} ${result.packageName} ${OutputHelper.formatDim('──')} ${colorStatus(formatStatusText(status), status.severity)}`);
147
141
  if (result.logs) {
148
142
  console.log(result.logs);
149
143
  }
@@ -155,6 +149,12 @@ export class SpinnerReporter extends BaseReporter {
155
149
  }
156
150
  console.log('');
157
151
  }
152
+ _resolve(result) {
153
+ return resolveResultStatus(result, {
154
+ successLabel: this._options.successLabel,
155
+ failureLabel: this._options.failureLabel,
156
+ });
157
+ }
158
158
  _render() {
159
159
  const lines = [];
160
160
  const spinner = SPINNER_FRAMES[this._spinnerFrame];
@@ -169,28 +169,13 @@ export class SpinnerReporter extends BaseReporter {
169
169
  const statusText = OutputHelper.formatDim('Queued');
170
170
  line = ` ${icon} ${OutputHelper.formatDim(state.name.padEnd(30))} ${statusText}`;
171
171
  }
172
- else if (state.status === 'passed') {
173
- const icon = OutputHelper.formatSuccess('✓');
174
- const progressText = formatProgressResult(state.result?.progressSummary);
175
- const label = this._options.successLabel ?? 'Passed';
176
- const empty = isEmptyTestRun(state.result?.progressSummary);
177
- let plain = progressText ? `${label} ${progressText}` : label;
178
- if (empty)
179
- plain += ' ⚠';
180
- const padded = OutputHelper.padVisible(plain, STATUS_COLUMN_WIDTH);
181
- const statusText = empty
182
- ? OutputHelper.formatWarning(padded)
183
- : OutputHelper.formatSuccess(padded);
184
- line = ` ${icon} ${state.name.padEnd(30)} ${statusText} ${OutputHelper.formatDim(time)}`;
185
- }
186
- else if (state.status === 'failed') {
187
- const icon = OutputHelper.formatError('✗');
188
- const failedPhase = state.result?.failedPhase;
189
- const failureLabel = state.result?.failureLabel ?? this._options.failureLabel ?? 'FAILED';
190
- const plain = failedPhase
191
- ? `${failureLabel} at ${failedPhase}`
192
- : failureLabel;
193
- const statusText = OutputHelper.formatError(plain.padEnd(STATUS_COLUMN_WIDTH));
172
+ else if (state.status === 'passed' || state.status === 'failed') {
173
+ // Both terminal states through one resolver: a pass that ran no tests
174
+ // and a pass whose logs went missing are warnings, and deciding that
175
+ // here is how the spinner and the table came to disagree about them.
176
+ const status = this._resolve(state.result ?? { success: state.status === 'passed' });
177
+ const icon = colorStatus(statusIcon(status.severity, 'ascii'), status.severity);
178
+ const statusText = colorStatus(OutputHelper.padVisible(formatStatusText(status), STATUS_COLUMN_WIDTH), status.severity);
194
179
  line = ` ${icon} ${state.name.padEnd(30)} ${statusText} ${OutputHelper.formatDim(time)}`;
195
180
  }
196
181
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"spinner-reporter.js","sourceRoot":"","sources":["../../src/reporting/spinner-reporter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spinner-reporter.js","sourceRoot":"","sources":["../../src/reporting/spinner-reporter.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,11 @@ export interface SummaryTableReporterOptions {
7
7
  failureLabel?: string;
8
8
  /** Verb in the footer, e.g. "tested" in "X tested, Y passed, Z failed". Default: "tested" */
9
9
  summaryVerb?: string;
10
+ /**
11
+ * True when this kind of run should have reported test counts, so a result
12
+ * with none is flagged rather than shown as a plain pass.
13
+ */
14
+ expectsTestCounts?: boolean;
10
15
  }
11
16
  /**
12
17
  * Prints a final summary table of all results when jobs complete.
@@ -17,9 +22,9 @@ export declare class SummaryTableReporter extends BaseReporter {
17
22
  private _successLabel;
18
23
  private _failureLabel;
19
24
  private _summaryVerb;
25
+ private _expectsTestCounts;
20
26
  constructor(state: IStateTracker, options?: SummaryTableReporterOptions);
21
27
  stopAsync(): Promise<void>;
22
- private _statusLabel;
23
- private _colorStatus;
28
+ private _resolve;
24
29
  }
25
30
  //# sourceMappingURL=summary-table-reporter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"summary-table-reporter.d.ts","sourceRoot":"","sources":["../../src/reporting/summary-table-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAsB,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9D,MAAM,WAAW,2BAA2B;IAC1C,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;gBAEjB,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,2BAA2B;IAQxD,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IA2DzC,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,YAAY;CAcrB"}
1
+ {"version":3,"file":"summary-table-reporter.d.ts","sourceRoot":"","sources":["../../src/reporting/summary-table-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAsB,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAS9D,MAAM,WAAW,2BAA2B;IAC1C,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,kBAAkB,CAAU;gBAExB,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,2BAA2B;IASxD,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IA0DzC,OAAO,CAAC,QAAQ;CAOjB"}
@@ -2,7 +2,7 @@ import { OutputHelper } from '../outputHelper.js';
2
2
  import { formatDurationMs } from '../cli-utils.js';
3
3
  import { BaseReporter } from './reporter.js';
4
4
  import { formatTable } from './format-table.js';
5
- import { formatProgressResult, isEmptyTestRun } from './progress-format.js';
5
+ import { colorStatus, formatStatusText, resolveResultStatus, tallyCaveats, } from './result-status.js';
6
6
  /**
7
7
  * Prints a final summary table of all results when jobs complete.
8
8
  * All output happens in stopAsync().
@@ -12,12 +12,14 @@ export class SummaryTableReporter extends BaseReporter {
12
12
  _successLabel;
13
13
  _failureLabel;
14
14
  _summaryVerb;
15
+ _expectsTestCounts;
15
16
  constructor(state, options) {
16
17
  super();
17
18
  this._state = state;
18
19
  this._successLabel = options?.successLabel ?? 'Passed';
19
20
  this._failureLabel = options?.failureLabel ?? 'FAILED';
20
21
  this._summaryVerb = options?.summaryVerb ?? 'tested';
22
+ this._expectsTestCounts = options?.expectsTestCounts ?? false;
21
23
  }
22
24
  async stopAsync() {
23
25
  const results = this._state
@@ -29,7 +31,9 @@ export class SummaryTableReporter extends BaseReporter {
29
31
  const failures = this._state.getFailures();
30
32
  const passed = results.length - failures.length;
31
33
  const durationMs = Date.now() - this._state.startTimeMs;
32
- let emptyRunCount = 0;
34
+ // Resolved once per result and reused for the row and the footer, so the
35
+ // tally under the table cannot disagree with the rows in it.
36
+ const statuses = new Map(results.map((result) => [result, this._resolve(result)]));
33
37
  const columns = [
34
38
  {
35
39
  header: 'Package',
@@ -38,8 +42,8 @@ export class SummaryTableReporter extends BaseReporter {
38
42
  },
39
43
  {
40
44
  header: 'Status',
41
- value: (r) => this._statusLabel(r),
42
- format: (label, r) => this._colorStatus(label, r, () => emptyRunCount++),
45
+ value: (r) => formatStatusText(statuses.get(r)),
46
+ format: (label, r) => colorStatus(label, statuses.get(r).severity),
43
47
  minWidth: 26,
44
48
  },
45
49
  {
@@ -58,31 +62,16 @@ export class SummaryTableReporter extends BaseReporter {
58
62
  const totalTime = OutputHelper.formatDim(`in ${formatDurationMs(durationMs)}`);
59
63
  const unit = results.length === 1 ? 'package' : 'packages';
60
64
  console.log(`${results.length} ${unit} ${this._summaryVerb}, ${passedText}, ${failedText} ${totalTime}`);
61
- if (emptyRunCount > 0) {
62
- console.log(OutputHelper.formatWarning(`⚠ ${emptyRunCount} package(s) ran 0 tests — check test discovery`));
65
+ for (const { message } of tallyCaveats([...statuses.values()])) {
66
+ console.log(OutputHelper.formatWarning(`⚠ ${message}`));
63
67
  }
64
68
  }
65
- _statusLabel(result) {
66
- if (result.success) {
67
- const progressText = formatProgressResult(result.progressSummary);
68
- return progressText
69
- ? `${this._successLabel} ${progressText}`
70
- : this._successLabel;
71
- }
72
- const failedPhase = result.failedPhase;
73
- const failureLabel = result.failureLabel ?? this._failureLabel;
74
- return failedPhase ? `${failureLabel} at ${failedPhase}` : failureLabel;
75
- }
76
- _colorStatus(label, result, countEmpty) {
77
- if (result.success) {
78
- const empty = isEmptyTestRun(result.progressSummary);
79
- if (empty)
80
- countEmpty();
81
- return empty
82
- ? OutputHelper.formatWarning(label)
83
- : OutputHelper.formatSuccess(label);
84
- }
85
- return OutputHelper.formatError(label);
69
+ _resolve(result) {
70
+ return resolveResultStatus(result, {
71
+ successLabel: this._successLabel,
72
+ failureLabel: this._failureLabel,
73
+ expectsTestCounts: this._expectsTestCounts,
74
+ });
86
75
  }
87
76
  }
88
77
  //# sourceMappingURL=summary-table-reporter.js.map