Skip to content

Commit 72e82e9

Browse files
committed
test_runner: print formatted errors on summary
1 parent 2bd5694 commit 72e82e9

File tree

4 files changed

+112
-19
lines changed

4 files changed

+112
-19
lines changed

lib/internal/test_runner/reporter/spec.js

+32-19
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,32 @@ class SpecReporter extends Transform {
3030
colors.refresh();
3131
}
3232

33+
#formatFailedTestResults() {
34+
if (this.#failedTests.length === 0) {
35+
return '';
36+
}
37+
38+
const results = [
39+
`\n${reporterColorMap['test:fail']}${reporterUnicodeSymbolMap['test:fail']}failing tests:${colors.white}\n`,
40+
];
41+
42+
for (let i = 0; i < this.#failedTests.length; i++) {
43+
const test = this.#failedTests[i];
44+
const formattedErr = formatTestReport('test:fail', test);
45+
46+
if (test.file) {
47+
const relPath = relative(this.#cwd, test.file);
48+
const location = `test at ${relPath}:${test.line}:${test.column}`;
49+
ArrayPrototypePush(results, location);
50+
}
51+
52+
ArrayPrototypePush(results, formattedErr);
53+
}
54+
55+
const output = ArrayPrototypeJoin(results, '\n');
56+
this.#failedTests = []; // Clean up the failed tests
57+
return output;
58+
}
3359
#handleTestReportEvent(type, data) {
3460
const subtest = ArrayPrototypeShift(this.#stack); // This is the matching `test:start` event
3561
if (subtest) {
@@ -74,31 +100,18 @@ class SpecReporter extends Transform {
74100
case 'test:coverage':
75101
return getCoverageReport(indent(data.nesting), data.summary,
76102
reporterUnicodeSymbolMap['test:coverage'], colors.blue, true);
103+
case 'test:summary':
104+
// We report only the root test summary
105+
if (data.file === undefined){
106+
return this.#formatFailedTestResults();
107+
}
77108
}
78109
}
79110
_transform({ type, data }, encoding, callback) {
80111
callback(null, this.#handleEvent({ __proto__: null, type, data }));
81112
}
82113
_flush(callback) {
83-
if (this.#failedTests.length === 0) {
84-
callback(null, '');
85-
return;
86-
}
87-
const results = [`\n${reporterColorMap['test:fail']}${reporterUnicodeSymbolMap['test:fail']}failing tests:${colors.white}\n`];
88-
for (let i = 0; i < this.#failedTests.length; i++) {
89-
const test = this.#failedTests[i];
90-
const formattedErr = formatTestReport('test:fail', test);
91-
92-
if (test.file) {
93-
const relPath = relative(this.#cwd, test.file);
94-
const location = `test at ${relPath}:${test.line}:${test.column}`;
95-
96-
ArrayPrototypePush(results, location);
97-
}
98-
99-
ArrayPrototypePush(results, formattedErr);
100-
}
101-
callback(null, ArrayPrototypeJoin(results, '\n'));
114+
callback(null, this.#formatFailedTestResults());
102115
}
103116
}
104117

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { run } from 'node:test';
2+
import { spec } from 'node:test/reporters';
3+
import tmpdir from '../../../common/tmpdir.js';
4+
import { writeFileSync } from 'node:fs';
5+
6+
7+
const fixtureContent = {
8+
'dependency.js': 'module.exports = {};',
9+
'dependency.mjs': 'export const a = 1;',
10+
'test.js': `
11+
const test = require('node:test');
12+
require('./dependency.js');
13+
import('./dependency.mjs');
14+
import('data:text/javascript,');
15+
test('test has ran');`,
16+
'failing-test.js': `
17+
const test = require('node:test');
18+
test('failing test', () => {
19+
throw new Error('failed');
20+
});`,
21+
};
22+
23+
tmpdir.refresh();
24+
25+
const fixturePaths = Object.keys(fixtureContent)
26+
.reduce((acc, file) => ({ ...acc, [file]: tmpdir.resolve(file) }), {});
27+
Object.entries(fixtureContent)
28+
.forEach(([file, content]) => writeFileSync(fixturePaths[file], content));
29+
30+
const controller = new AbortController();
31+
const { signal } = controller;
32+
33+
const stream = run({
34+
watch: true,
35+
cwd: tmpdir.path,
36+
signal,
37+
});
38+
39+
40+
stream.compose(spec).pipe(process.stdout);
41+
42+
for await (const event of stream) {
43+
if (event.type === 'test:watch:drained') {
44+
controller.abort();
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
✖ failing test (*ms)
2+
✔ test has ran (*ms)
3+
ℹ tests 2
4+
ℹ suites 0
5+
ℹ pass 1
6+
ℹ fail 1
7+
ℹ cancelled 0
8+
ℹ skipped 0
9+
ℹ todo 0
10+
ℹ duration_ms *
11+
12+
✖ failing tests:
13+
14+
*
15+
✖ failing test (*ms)
16+
Error: failed
17+
*
18+
*
19+
*
20+
*
21+
*
22+
*
23+
ℹ tests 0
24+
ℹ suites 0
25+
ℹ pass 0
26+
ℹ fail 0
27+
ℹ cancelled 0
28+
ℹ skipped 0
29+
ℹ todo 0
30+
ℹ duration_ms *

test/parallel/test-runner-output.mjs

+4
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ const tests = [
235235
name: 'test-runner/output/test-runner-plan.js',
236236
flags: ['--test-reporter=tap'],
237237
},
238+
{
239+
name: 'test-runner/output/test-runner-watch-spec.mjs',
240+
transform: specTransform,
241+
},
238242
process.features.inspector ? {
239243
name: 'test-runner/output/coverage_failure.js',
240244
flags: ['--test-reporter=tap', '--test-coverage-exclude=!test/**'],

0 commit comments

Comments
 (0)