Skip to content

Commit 6d254a0

Browse files
committed
test: fix test runner does not print error cause
1 parent 85c8b78 commit 6d254a0

6 files changed

+92
-12
lines changed

lib/internal/test_runner/reporter/tap.js

+14-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const {
1414
const { inspectWithNoCustomRetry } = require('internal/errors');
1515
const { isError, kEmptyObject } = require('internal/util');
1616
const { relative } = require('path');
17+
const util = require('util');
1718
const kDefaultIndent = ' '; // 4 spaces
1819
const kFrameStartRegExp = /^ {4}at /;
1920
const kLineBreakRegExp = /\n|\r\n/;
@@ -196,6 +197,7 @@ function jsToYaml(indent, name, value) {
196197
operator,
197198
stack,
198199
} = value;
200+
const errHasInnerCause = hasInnerCause(value);
199201
let errMsg = message ?? '<unknown error>';
200202
let errStack = stack;
201203
let errCode = code;
@@ -207,7 +209,11 @@ function jsToYaml(indent, name, value) {
207209
// If the ERR_TEST_FAILURE came from an error provided by user code,
208210
// then try to unwrap the original error message and stack.
209211
if (code === 'ERR_TEST_FAILURE' && kUnwrapErrors.has(failureType)) {
210-
errStack = cause?.stack ?? errStack;
212+
if (errHasInnerCause) {
213+
errStack = util.inspect(cause);
214+
} else {
215+
errStack = cause?.stack ?? errStack;
216+
}
211217
errCode = cause?.code ?? errCode;
212218
if (isAssertionLike(cause)) {
213219
errExpected = cause.expected;
@@ -245,8 +251,9 @@ function jsToYaml(indent, name, value) {
245251
frame,
246252
''
247253
);
248-
249-
if (processed.length > 0 && processed.length !== frame.length) {
254+
if (errHasInnerCause && processed.length > 0) {
255+
ArrayPrototypePush(frames, processed);
256+
} else if (processed.length > 0 && processed.length !== frame.length) {
250257
ArrayPrototypePush(frames, processed);
251258
}
252259
}
@@ -268,4 +275,8 @@ function isAssertionLike(value) {
268275
return value && typeof value === 'object' && 'expected' in value && 'actual' in value;
269276
}
270277

278+
function hasInnerCause(value) {
279+
return value?.cause?.cause?.stack ? true : false;
280+
}
281+
271282
module.exports = tapReporter;

test/message/test_runner_output.js

+4
Original file line numberDiff line numberDiff line change
@@ -383,3 +383,7 @@ test('unfinished test with unhandledRejection', async () => {
383383
setTimeout(() => Promise.reject(new Error('bar')));
384384
});
385385
});
386+
387+
test('should print error cause', () => {
388+
throw new Error('foo', { cause: new Error('bar') });
389+
});

test/message/test_runner_output.out

+28-4
Original file line numberDiff line numberDiff line change
@@ -620,8 +620,32 @@ not ok 64 - unfinished test with unhandledRejection
620620
*
621621
*
622622
...
623+
# Subtest: should print error cause
624+
not ok 65 - should print error cause
625+
---
626+
duration_ms: *
627+
failureType: 'testCodeFailure'
628+
error: 'foo'
629+
code: 'ERR_TEST_FAILURE'
630+
stack: |-
631+
*
632+
*
633+
*
634+
*
635+
*
636+
*
637+
*
638+
*
639+
*
640+
*
641+
*
642+
*
643+
*
644+
*
645+
*
646+
...
623647
# Subtest: invalid subtest fail
624-
not ok 65 - invalid subtest fail
648+
not ok 66 - invalid subtest fail
625649
---
626650
duration_ms: *
627651
failureType: 'parentAlreadyFinished'
@@ -630,16 +654,16 @@ not ok 65 - invalid subtest fail
630654
stack: |-
631655
*
632656
...
633-
1..65
657+
1..66
634658
# Warning: Test "unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
635659
# Warning: Test "async unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from async unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
636660
# Warning: Test "immediate throw - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from immediate throw fail" and would have caused the test to fail, but instead triggered an uncaughtException event.
637661
# Warning: Test "immediate reject - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from immediate reject fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
638662
# Warning: Test "callback called twice in different ticks" generated asynchronous activity after the test ended. This activity created the error "Error [ERR_TEST_FAILURE]: callback invoked multiple times" and would have caused the test to fail, but instead triggered an uncaughtException event.
639663
# Warning: Test "callback async throw after done" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from callback async throw after done" and would have caused the test to fail, but instead triggered an uncaughtException event.
640-
# tests 65
664+
# tests 66
641665
# pass 27
642-
# fail 21
666+
# fail 22
643667
# cancelled 2
644668
# skipped 10
645669
# todo 5

test/message/test_runner_output_cli.out

+26-2
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,32 @@ TAP version 13
621621
*
622622
*
623623
...
624+
# Subtest: should print error cause
625+
not ok 65 - should print error cause
626+
---
627+
duration_ms: *
628+
failureType: 'testCodeFailure'
629+
error: 'foo'
630+
code: 'ERR_TEST_FAILURE'
631+
stack: |-
632+
*
633+
*
634+
*
635+
636+
*
637+
*
638+
*
639+
*
640+
*
641+
*
642+
*
643+
*
644+
*
645+
*
646+
*
647+
...
624648
# Subtest: invalid subtest fail
625-
not ok 65 - invalid subtest fail
649+
not ok 66 - invalid subtest fail
626650
---
627651
duration_ms: *
628652
failureType: 'parentAlreadyFinished'
@@ -631,7 +655,7 @@ TAP version 13
631655
stack: |-
632656
*
633657
...
634-
1..65
658+
1..66
635659
# Warning: Test "unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
636660
# Warning: Test "async unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from async unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
637661
# Warning: Test "immediate throw - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from immediate throw fail" and would have caused the test to fail, but instead triggered an uncaughtException event.
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
..XX...X..XXX.X.....
22
XXX.....X..X...X....
33
.........X...XXX.XX.
4-
.....XXXXXXX...XXXX
4+
.....XXXXXXX...XXXXX

test/message/test_runner_output_spec_reporter.out

+19-2
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,23 @@
262262
*
263263
*
264264

265+
should print error cause (*ms)
266+
Error: foo
267+
*
268+
*
269+
*
270+
*
271+
*
272+
*
273+
*
274+
*
275+
*
276+
*
277+
*
278+
*
279+
*
280+
*
281+
265282
invalid subtest fail (*ms)
266283
'test could not be started because its parent finished'
267284

@@ -271,9 +288,9 @@
271288
Warning: Test "immediate reject - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from immediate reject fail" and would have caused the test to fail, but instead triggered an unhandledRejection event.
272289
Warning: Test "callback called twice in different ticks" generated asynchronous activity after the test ended. This activity created the error "Error [ERR_TEST_FAILURE]: callback invoked multiple times" and would have caused the test to fail, but instead triggered an uncaughtException event.
273290
Warning: Test "callback async throw after done" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from callback async throw after done" and would have caused the test to fail, but instead triggered an uncaughtException event.
274-
tests 65
291+
tests 66
275292
pass 27
276-
fail 21
293+
fail 22
277294
cancelled 2
278295
skipped 10
279296
todo 5

0 commit comments

Comments
 (0)