Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 644e239

Browse filesBrowse files
MoLowaduh95
authored andcommitted
test_runner: add getTestContext()
PR-URL: #62501 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
1 parent db66a96 commit 644e239
Copy full SHA for 644e239

5 files changed

+116-2Lines changed: 116 additions & 2 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎doc/api/test.md‎

Copy file name to clipboardExpand all lines: doc/api/test.md
+38Lines changed: 38 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -3563,6 +3563,44 @@ Emitted when no more tests are queued for execution in watch mode.
35633563

35643564
Emitted when one or more tests are restarted due to a file change in watch mode.
35653565

3566+
## `getTestContext()`
3567+
3568+
<!-- YAML
3569+
added: REPLACEME
3570+
-->
3571+
3572+
* Returns: {TestContext|SuiteContext|undefined}
3573+
3574+
Returns the [`TestContext`][] or [`SuiteContext`][] object associated with the
3575+
currently executing test or suite, or `undefined` if called outside of a test or
3576+
suite. This function can be used to access context information from within the
3577+
test or suite function or any async operations within them.
3578+
3579+
```mjs
3580+
import { getTestContext } from 'node:test';
3581+
3582+
test('example test', async () => {
3583+
const ctx = getTestContext();
3584+
console.log(`Running test: ${ctx.name}`);
3585+
});
3586+
3587+
describe('example suite', () => {
3588+
const ctx = getTestContext();
3589+
console.log(`Running suite: ${ctx.name}`);
3590+
});
3591+
```
3592+
3593+
When called from a test, returns a [`TestContext`][].
3594+
When called from a suite, returns a [`SuiteContext`][].
3595+
3596+
If called from outside a test or suite (e.g., at the top level of a module or in
3597+
a setTimeout callback after execution has completed), this function returns
3598+
`undefined`.
3599+
3600+
When called from within a hook (before, beforeEach, after, afterEach), this
3601+
function returns the context of the test or suite that the hook is associated
3602+
with.
3603+
35663604
## Class: `TestContext`
35673605

35683606
<!-- YAML
Collapse file

‎lib/internal/test_runner/harness.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/harness.js
+20-1Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const {
2121
},
2222
} = require('internal/errors');
2323
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
24-
const { kCancelledByParent, Test, Suite } = require('internal/test_runner/test');
24+
const { kCancelledByParent, Test, Suite, TestContext, SuiteContext } = require('internal/test_runner/test');
2525
const {
2626
parseCommandLine,
2727
reporterScope,
@@ -431,8 +431,27 @@ function hook(hook) {
431431
};
432432
}
433433

434+
function getTestContext() {
435+
const test = testResources.get(executionAsyncId());
436+
// Exclude the reporter sentinel
437+
if (test === undefined || test === reporterScope) {
438+
return undefined;
439+
}
440+
// For hooks (hookType is set), return the test/suite being hooked (the parent)
441+
const actualTest = test.hookType !== undefined ? test.parent : test;
442+
if (actualTest === undefined) {
443+
return undefined;
444+
}
445+
// Return SuiteContext for suites, TestContext for tests
446+
if (actualTest instanceof Suite) {
447+
return new SuiteContext(actualTest);
448+
}
449+
return new TestContext(actualTest);
450+
}
451+
434452
module.exports = {
435453
createTestTree,
454+
getTestContext,
436455
test: runInParentContext(Test),
437456
suite: runInParentContext(Suite),
438457
before: hook('before'),
Collapse file

‎lib/internal/test_runner/test.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/test.js
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,4 +1656,6 @@ module.exports = {
16561656
kUnwrapErrors,
16571657
Suite,
16581658
Test,
1659+
TestContext,
1660+
SuiteContext,
16591661
};
Collapse file

‎lib/test.js‎

Copy file name to clipboardExpand all lines: lib/test.js
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const {
55
ObjectDefineProperty,
66
} = primordials;
77

8-
const { test, suite, before, after, beforeEach, afterEach } = require('internal/test_runner/harness');
8+
const { test, suite, before, after, beforeEach, afterEach, getTestContext } = require('internal/test_runner/harness');
99
const { run } = require('internal/test_runner/runner');
1010

1111
module.exports = test;
@@ -15,6 +15,7 @@ ObjectAssign(module.exports, {
1515
before,
1616
beforeEach,
1717
describe: suite,
18+
getTestContext,
1819
it: test,
1920
run,
2021
suite,
Collapse file
+54Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('node:assert');
4+
const { test, getTestContext, describe, it } = require('node:test');
5+
6+
// Outside a test — must return undefined
7+
assert.strictEqual(getTestContext(), undefined);
8+
9+
test('getTestContext returns current context inside test', async () => {
10+
const ctx = getTestContext();
11+
assert.ok(ctx !== undefined);
12+
assert.strictEqual(ctx.name, 'getTestContext returns current context inside test');
13+
assert.strictEqual(typeof ctx.signal, 'object');
14+
assert.strictEqual(typeof ctx.fullName, 'string');
15+
});
16+
17+
test('getTestContext works in nested test', async (t) => {
18+
await t.test('child', async () => {
19+
const ctx = getTestContext();
20+
assert.ok(ctx !== undefined);
21+
assert.strictEqual(ctx.name, 'child');
22+
});
23+
});
24+
25+
describe('getTestContext works in describe/it', () => {
26+
it('has correct name', () => {
27+
const ctx = getTestContext();
28+
assert.ok(ctx !== undefined);
29+
assert.strictEqual(ctx.name, 'has correct name');
30+
});
31+
});
32+
33+
describe('getTestContext returns SuiteContext in suite', () => {
34+
it('suite context is available', () => {
35+
const ctx = getTestContext();
36+
assert.ok(ctx !== undefined);
37+
// Suite name appears as parent in nested test context
38+
assert.strictEqual(typeof ctx.signal, 'object');
39+
assert.strictEqual(typeof ctx.fullName, 'string');
40+
});
41+
});
42+
43+
test('getTestContext works in test body during async operations', async (t) => {
44+
const ctx = getTestContext();
45+
assert.ok(ctx !== undefined);
46+
assert.strictEqual(ctx.name, 'getTestContext works in test body during async operations');
47+
48+
// Also works in nested async context
49+
const ctxInSetImmediate = await new Promise((resolve) => {
50+
setImmediate(() => resolve(getTestContext()));
51+
});
52+
assert.ok(ctxInSetImmediate !== undefined);
53+
assert.strictEqual(ctxInSetImmediate.name, 'getTestContext works in test body during async operations');
54+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.