Skip to content

Commit 8b0c5ed

Browse files
romainmenkeRafaelGSS
authored andcommitted
Revert "test_runner: remove promises returned by test()"
This reverts commit 9671826. PR-URL: #58282 Fixes: #58227 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: LiviaMedeiros <[email protected]>
1 parent 6ef7329 commit 8b0c5ed

File tree

5 files changed

+47
-23
lines changed

5 files changed

+47
-23
lines changed

doc/api/test.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,11 +1472,6 @@ run({ files: [path.resolve('./tests/test.js')] })
14721472
added:
14731473
- v22.0.0
14741474
- v20.13.0
1475-
changes:
1476-
- version:
1477-
- v24.0.0
1478-
pr-url: https://github.com/nodejs/node/pull/56664
1479-
description: This function no longer returns a `Promise`.
14801475
-->
14811476

14821477
* `name` {string} The name of the suite, which is displayed when reporting test
@@ -1487,6 +1482,7 @@ changes:
14871482
* `fn` {Function|AsyncFunction} The suite function declaring nested tests and
14881483
suites. The first argument to this function is a [`SuiteContext`][] object.
14891484
**Default:** A no-op function.
1485+
* Returns: {Promise} Immediately fulfilled with `undefined`.
14901486

14911487
The `suite()` function is imported from the `node:test` module.
14921488

@@ -1530,10 +1526,6 @@ added:
15301526
- v18.0.0
15311527
- v16.17.0
15321528
changes:
1533-
- version:
1534-
- v24.0.0
1535-
pr-url: https://github.com/nodejs/node/pull/56664
1536-
description: This function no longer returns a `Promise`.
15371529
- version:
15381530
- v20.2.0
15391531
- v18.17.0
@@ -1583,6 +1575,8 @@ changes:
15831575
to this function is a [`TestContext`][] object. If the test uses callbacks,
15841576
the callback function is passed as the second argument. **Default:** A no-op
15851577
function.
1578+
* Returns: {Promise} Fulfilled with `undefined` once
1579+
the test completes, or immediately if the test runs within a suite.
15861580

15871581
The `test()` function is the value imported from the `test` module. Each
15881582
invocation of this function results in reporting the test to the {TestsStream}.
@@ -1591,6 +1585,26 @@ The `TestContext` object passed to the `fn` argument can be used to perform
15911585
actions related to the current test. Examples include skipping the test, adding
15921586
additional diagnostic information, or creating subtests.
15931587

1588+
`test()` returns a `Promise` that fulfills once the test completes.
1589+
if `test()` is called within a suite, it fulfills immediately.
1590+
The return value can usually be discarded for top level tests.
1591+
However, the return value from subtests should be used to prevent the parent
1592+
test from finishing first and cancelling the subtest
1593+
as shown in the following example.
1594+
1595+
```js
1596+
test('top level test', async (t) => {
1597+
// The setTimeout() in the following subtest would cause it to outlive its
1598+
// parent test if 'await' is removed on the next line. Once the parent test
1599+
// completes, it will cancel any outstanding subtests.
1600+
await t.test('longer running subtest', async (t) => {
1601+
return new Promise((resolve, reject) => {
1602+
setTimeout(resolve, 1000);
1603+
});
1604+
});
1605+
});
1606+
```
1607+
15941608
The `timeout` option can be used to fail the test if it takes longer than
15951609
`timeout` milliseconds to complete. However, it is not a reliable mechanism for
15961610
canceling tests because a running test might block the application thread and

lib/internal/test_runner/harness.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -325,12 +325,11 @@ function runInParentContext(Factory) {
325325
function run(name, options, fn, overrides) {
326326
const parent = testResources.get(executionAsyncId()) || lazyBootstrapRoot();
327327
const subtest = parent.createSubtest(Factory, name, options, fn, overrides);
328-
329328
if (parent instanceof Suite) {
330-
return;
329+
return PromiseResolve();
331330
}
332331

333-
startSubtestAfterBootstrap(subtest);
332+
return startSubtestAfterBootstrap(subtest);
334333
}
335334

336335
const test = (name, options, fn) => {
@@ -339,7 +338,7 @@ function runInParentContext(Factory) {
339338
loc: getCallerLocation(),
340339
};
341340

342-
run(name, options, fn, overrides);
341+
return run(name, options, fn, overrides);
343342
};
344343
ArrayPrototypeForEach(['skip', 'todo', 'only'], (keyword) => {
345344
test[keyword] = (name, options, fn) => {
@@ -349,7 +348,7 @@ function runInParentContext(Factory) {
349348
loc: getCallerLocation(),
350349
};
351350

352-
run(name, options, fn, overrides);
351+
return run(name, options, fn, overrides);
353352
};
354353
});
355354
return test;

test/parallel/test-runner-coverage-source-map.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,4 @@ describe('Coverage with source maps', async () => {
122122
t.assert.strictEqual(spawned.code, 1);
123123
});
124124
}
125-
});
125+
}).then(common.mustCall());

test/parallel/test-runner-misc.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ if (process.argv[2] === 'child') {
1818
assert.strictEqual(signal.aborted, false);
1919
testSignal = signal;
2020
await setTimeout(50);
21+
})).finally(common.mustCall(() => {
22+
test(() => assert.strictEqual(testSignal.aborted, true));
2123
}));
22-
test(() => assert.strictEqual(testSignal.aborted, true));
2324

2425
// TODO(benjamingr) add more tests to describe + AbortSignal
2526
// this just tests the parameter is passed

test/parallel/test-runner-typechecking.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require('../common');
66

77
const assert = require('assert');
88
const { test, describe, it } = require('node:test');
9+
const { isPromise } = require('util/types');
910

1011
const testOnly = test('only test', { only: true });
1112
const testTodo = test('todo test', { todo: true });
@@ -15,12 +16,21 @@ const testTodoShorthand = test.todo('todo test shorthand');
1516
const testSkipShorthand = test.skip('skip test shorthand');
1617

1718
describe('\'node:test\' and its shorthands should return the same', () => {
18-
it('should return undefined', () => {
19-
assert.strictEqual(testOnly, undefined);
20-
assert.strictEqual(testTodo, undefined);
21-
assert.strictEqual(testSkip, undefined);
22-
assert.strictEqual(testOnlyShorthand, undefined);
23-
assert.strictEqual(testTodoShorthand, undefined);
24-
assert.strictEqual(testSkipShorthand, undefined);
19+
it('should return a Promise', () => {
20+
assert(isPromise(testOnly));
21+
assert(isPromise(testTodo));
22+
assert(isPromise(testSkip));
23+
assert(isPromise(testOnlyShorthand));
24+
assert(isPromise(testTodoShorthand));
25+
assert(isPromise(testSkipShorthand));
26+
});
27+
28+
it('should resolve undefined', async () => {
29+
assert.strictEqual(await testOnly, undefined);
30+
assert.strictEqual(await testTodo, undefined);
31+
assert.strictEqual(await testSkip, undefined);
32+
assert.strictEqual(await testOnlyShorthand, undefined);
33+
assert.strictEqual(await testTodoShorthand, undefined);
34+
assert.strictEqual(await testSkipShorthand, undefined);
2535
});
2636
});

0 commit comments

Comments
 (0)