Skip to content

Commit cf817e1

Browse files
MoLowmarco-ippolito
authored andcommittedJun 17, 2024
test_runner: preserve hook promise when executed twice
PR-URL: #52791 Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1 parent a5f3dd1 commit cf817e1

File tree

5 files changed

+86
-12
lines changed

5 files changed

+86
-12
lines changed
 

‎lib/internal/test_runner/test.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ const {
8787
let kResistStopPropagation;
8888
let findSourceMap;
8989

90+
const kRunOnceOptions = { __proto__: null, preserveReturnValue: true };
91+
9092
function lazyFindSourceMap(file) {
9193
if (findSourceMap === undefined) {
9294
({ findSourceMap } = require('internal/source_map/source_map_cache'));
@@ -526,7 +528,7 @@ class Test extends AsyncResource {
526528
// eslint-disable-next-line no-use-before-define
527529
const hook = new TestHook(fn, options);
528530
if (name === 'before' || name === 'after') {
529-
hook.run = runOnce(hook.run);
531+
hook.run = runOnce(hook.run, kRunOnceOptions);
530532
}
531533
if (name === 'before' && this.startTime !== null) {
532534
// Test has already started, run the hook immediately
@@ -650,7 +652,7 @@ class Test extends AsyncResource {
650652
if (this.parent?.hooks.afterEach.length > 0 && !this.skipped) {
651653
await this.parent.runHook('afterEach', hookArgs);
652654
}
653-
});
655+
}, kRunOnceOptions);
654656

655657
let stopPromise;
656658

@@ -1004,7 +1006,7 @@ class Suite extends Test {
10041006
const hookArgs = this.getRunArgs();
10051007

10061008
let stopPromise;
1007-
const after = runOnce(() => this.runHook('after', hookArgs));
1009+
const after = runOnce(() => this.runHook('after', hookArgs), kRunOnceOptions);
10081010
try {
10091011
this.parent.activeSubtests++;
10101012
await this.buildSuite;

‎lib/internal/util.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -511,12 +511,15 @@ function isInsideNodeModules() {
511511
return false;
512512
}
513513

514-
function once(callback) {
514+
function once(callback, { preserveReturnValue = false } = kEmptyObject) {
515515
let called = false;
516+
let returnValue;
516517
return function(...args) {
517-
if (called) return;
518+
if (called) return returnValue;
518519
called = true;
519-
return ReflectApply(callback, this, args);
520+
const result = ReflectApply(callback, this, args);
521+
returnValue = preserveReturnValue ? result : undefined;
522+
return result;
520523
};
521524
}
522525

‎test/fixtures/test-runner/output/hooks.js

+50-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
const common = require('../../../common');
33
const assert = require('assert');
44
const { test, describe, it, before, after, beforeEach, afterEach } = require('node:test');
5+
const { setTimeout } = require('node:timers/promises');
56

67
before((t) => t.diagnostic('before 1 called'));
78
after((t) => t.diagnostic('after 1 called'));
@@ -148,7 +149,6 @@ test('test hooks', async (t) => {
148149
}));
149150
});
150151

151-
152152
test('test hooks - no subtests', async (t) => {
153153
const testArr = [];
154154

@@ -253,5 +253,54 @@ describe('run after when before throws', () => {
253253
it('1', () => {});
254254
});
255255

256+
257+
test('test hooks - async', async (t) => {
258+
const testArr = [];
259+
260+
t.before(async (t) => {
261+
testArr.push('before starting ' + t.name);
262+
await setTimeout(10);
263+
testArr.push('before ending ' + t.name);
264+
});
265+
t.after(async (t) => {
266+
testArr.push('after starting ' + t.name);
267+
await setTimeout(10);
268+
testArr.push('after ending ' + t.name);
269+
});
270+
t.beforeEach(async (t) => {
271+
testArr.push('beforeEach starting ' + t.name);
272+
await setTimeout(10);
273+
testArr.push('beforeEach ending ' + t.name);
274+
});
275+
t.afterEach(async (t) => {
276+
testArr.push('afterEach starting ' + t.name);
277+
await setTimeout(10);
278+
testArr.push('afterEach ending ' + t.name);
279+
});
280+
await t.test('1', async () => {
281+
testArr.push('1 starting');
282+
await setTimeout(10);
283+
testArr.push('1 ending');
284+
});
285+
await t.test('2', async () => {
286+
testArr.push('2 starting');
287+
await setTimeout(10);
288+
testArr.push('2 ending');
289+
});
290+
291+
t.after(common.mustCall(() => {
292+
assert.deepStrictEqual(testArr, [
293+
'before starting test hooks - async', 'before ending test hooks - async',
294+
'beforeEach starting 1', 'beforeEach ending 1',
295+
'1 starting', '1 ending',
296+
'afterEach starting 1', 'afterEach ending 1',
297+
'beforeEach starting 2', 'beforeEach ending 2',
298+
'2 starting', '2 ending',
299+
'afterEach starting 2', 'afterEach ending 2',
300+
'after starting test hooks - async', 'after ending test hooks - async',
301+
]);
302+
}));
303+
});
304+
256305
before((t) => t.diagnostic('before 2 called'));
257306
after((t) => t.diagnostic('after 2 called'));

‎test/fixtures/test-runner/output/hooks.snapshot

+19-3
Original file line numberDiff line numberDiff line change
@@ -767,14 +767,30 @@ not ok 24 - run after when before throws
767767
*
768768
*
769769
...
770-
1..24
770+
# Subtest: test hooks - async
771+
# Subtest: 1
772+
ok 1 - 1
773+
---
774+
duration_ms: *
775+
...
776+
# Subtest: 2
777+
ok 2 - 2
778+
---
779+
duration_ms: *
780+
...
781+
1..2
782+
ok 25 - test hooks - async
783+
---
784+
duration_ms: *
785+
...
786+
1..25
771787
# before 1 called
772788
# before 2 called
773789
# after 1 called
774790
# after 2 called
775-
# tests 49
791+
# tests 52
776792
# suites 12
777-
# pass 19
793+
# pass 22
778794
# fail 27
779795
# cancelled 3
780796
# skipped 0

‎test/fixtures/test-runner/output/hooks_spec_reporter.snapshot

+6-2
Original file line numberDiff line numberDiff line change
@@ -392,13 +392,17 @@
392392
*
393393
*
394394

395+
test hooks - async
396+
1 (*ms)
397+
2 (*ms)
398+
test hooks - async (*ms)
395399
before 1 called
396400
before 2 called
397401
after 1 called
398402
after 2 called
399-
tests 49
403+
tests 52
400404
suites 12
401-
pass 19
405+
pass 22
402406
fail 27
403407
cancelled 3
404408
skipped 0

0 commit comments

Comments
 (0)
Please sign in to comment.