lib: allow checking the test result from afterEach

PR-URL: https://github.com/nodejs/node/pull/51485
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
This commit is contained in:
Tim Stableford
2024-01-19 14:56:06 +00:00
committed by GitHub
parent fbf1fb3bed
commit d755f1ae88
5 changed files with 107 additions and 14 deletions

View File

@@ -132,6 +132,14 @@ class TestContext {
return this.#test.name;
}
get error() {
return this.#test.error;
}
get passed() {
return this.#test.passed;
}
diagnostic(message) {
this.#test.diagnostic(message);
}
@@ -639,12 +647,17 @@ class Test extends AsyncResource {
return;
}
await afterEach();
await after();
this.pass();
try {
await afterEach();
await after();
} catch (err) {
// If one of the after hooks has thrown unset endTime so that the
// catch below can do its cancel/fail logic.
this.endTime = null;
throw err;
}
} catch (err) {
try { await afterEach(); } catch { /* test is already failing, let's ignore the error */ }
try { await after(); } catch { /* Ignore error. */ }
if (isTestFailureError(err)) {
if (err.failureType === kTestTimeoutFailure) {
this.#cancel(err);
@@ -654,6 +667,8 @@ class Test extends AsyncResource {
} else {
this.fail(new ERR_TEST_FAILURE(err, kTestCodeFailure));
}
try { await afterEach(); } catch { /* test is already failing, let's ignore the error */ }
try { await after(); } catch { /* Ignore error. */ }
} finally {
stopPromise?.[SymbolDispose]();

View File

@@ -152,6 +152,25 @@ test('afterEach when test fails', async (t) => {
await t.test('2', () => {});
});
test('afterEach context when test passes', async (t) => {
t.afterEach(common.mustCall((ctx) => {
assert.strictEqual(ctx.name, '1');
assert.strictEqual(ctx.passed, true);
assert.strictEqual(ctx.error, null);
}));
await t.test('1', () => {});
});
test('afterEach context when test fails', async (t) => {
const err = new Error('test');
t.afterEach(common.mustCall((ctx) => {
assert.strictEqual(ctx.name, '1');
assert.strictEqual(ctx.passed, false);
assert.strictEqual(ctx.error, err);
}));
await t.test('1', () => { throw err });
});
test('afterEach throws and test fails', async (t) => {
t.after(common.mustCall());
t.afterEach(() => { throw new Error('afterEach'); });

View File

@@ -505,6 +505,41 @@ not ok 12 - afterEach when test fails
error: '1 subtest failed'
code: 'ERR_TEST_FAILURE'
...
# Subtest: afterEach context when test passes
# Subtest: 1
ok 1 - 1
---
duration_ms: *
...
1..1
ok 13 - afterEach context when test passes
---
duration_ms: *
...
# Subtest: afterEach context when test fails
# Subtest: 1
not ok 1 - 1
---
duration_ms: *
location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11'
failureType: 'testCodeFailure'
error: 'test'
code: 'ERR_TEST_FAILURE'
stack: |-
*
*
*
*
...
1..1
not ok 14 - afterEach context when test fails
---
duration_ms: *
location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1'
failureType: 'subtestsFailed'
error: '1 subtest failed'
code: 'ERR_TEST_FAILURE'
...
# Subtest: afterEach throws and test fails
# Subtest: 1
not ok 1 - 1
@@ -546,7 +581,7 @@ not ok 12 - afterEach when test fails
*
...
1..2
not ok 13 - afterEach throws and test fails
not ok 15 - afterEach throws and test fails
---
duration_ms: *
location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1'
@@ -555,7 +590,7 @@ not ok 13 - afterEach throws and test fails
code: 'ERR_TEST_FAILURE'
...
# Subtest: t.after() is called if test body throws
not ok 14 - t.after() is called if test body throws
not ok 16 - t.after() is called if test body throws
---
duration_ms: *
location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1'
@@ -580,7 +615,7 @@ not ok 14 - t.after() is called if test body throws
code: 'ERR_TEST_FAILURE'
...
1..1
not ok 15 - run after when before throws
not ok 17 - run after when before throws
---
duration_ms: *
type: 'suite'
@@ -599,15 +634,15 @@ not ok 15 - run after when before throws
*
*
...
1..15
1..17
# before 1 called
# before 2 called
# after 1 called
# after 2 called
# tests 39
# tests 43
# suites 9
# pass 14
# fail 22
# pass 16
# fail 24
# cancelled 3
# skipped 0
# todo 0

View File

@@ -258,6 +258,20 @@
2 (*ms)
afterEach when test fails (*ms)
afterEach context when test passes
1 (*ms)
afterEach context when test passes (*ms)
afterEach context when test fails
1 (*ms)
Error: test
*
*
*
*
afterEach context when test fails (*ms)
afterEach throws and test fails
1 (*ms)
Error: test
@@ -315,10 +329,10 @@
before 2 called
after 1 called
after 2 called
tests 39
tests 43
suites 9
pass 14
fail 22
pass 16
fail 24
cancelled 3
skipped 0
todo 0
@@ -551,6 +565,14 @@
*
*
*
1 (*ms)
Error: test
*
*
*
*
*
1 (*ms)
Error: test

View File

@@ -155,6 +155,7 @@ true !== false
<testcase name="+sync throw fail" time="*" classname="test" failure="thrown from subtest sync throw fail">
<failure type="testCodeFailure" message="thrown from subtest sync throw fail">
Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail
*
* {
code: 'ERR_TEST_FAILURE',
failureType: 'testCodeFailure',
@@ -338,6 +339,7 @@ Error [ERR_TEST_FAILURE]: thrown from callback async throw
<testcase name="sync throw fails at first" time="*" classname="test" failure="thrown from subtest sync throw fails at first">
<failure type="testCodeFailure" message="thrown from subtest sync throw fails at first">
Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at first
*
* {
code: 'ERR_TEST_FAILURE',
failureType: 'testCodeFailure',