Skip to content

Commit

Permalink
test_runner: add context.filePath
Browse files Browse the repository at this point in the history
This commit adds a filePath getter to the TestContext and
SuiteContext classes. This allows a context to be mapped back to
the original test file that created it, even if it was imported
from another file. This is useful for mapping features like test
snapshots to the correct test file. This is also prep work for
supporting running test files in the test runner process.

PR-URL: nodejs#53853
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Chemi Atlow <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
  • Loading branch information
cjihrig authored and ehsankhfr committed Jul 18, 2024
1 parent ab6ffb0 commit 91f8ced
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 2 deletions.
20 changes: 20 additions & 0 deletions doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -3204,6 +3204,16 @@ test('top level test', (t) => {
});
```

### `context.filePath`

<!-- YAML
added: REPLACEME
-->

The absolute path of the test file that created the current test. If a test file
imports additional modules that generate tests, the imported tests will return
the path of the root test file.

### `context.fullName`

<!-- YAML
Expand Down Expand Up @@ -3438,6 +3448,16 @@ An instance of `SuiteContext` is passed to each suite function in order to
interact with the test runner. However, the `SuiteContext` constructor is not
exposed as part of the API.

### `context.filePath`

<!-- YAML
added: REPLACEME
-->

The absolute path of the test file that created the current suite. If a test
file imports additional modules that generate suites, the imported suites will
return the path of the root test file.

### `context.name`

<!-- YAML
Expand Down
2 changes: 1 addition & 1 deletion lib/internal/test_runner/harness.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ let globalRoot;
let reportersSetup;
function getGlobalRoot() {
if (!globalRoot) {
globalRoot = createTestTree();
globalRoot = createTestTree({ __proto__: null, entryFile: process.argv?.[1] });
globalRoot.reporter.on('test:fail', (data) => {
if (data.todo === undefined || data.todo === false) {
process.exitCode = kGenericUserError;
Expand Down
12 changes: 11 additions & 1 deletion lib/internal/test_runner/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ class TestContext {
return this.#test.name;
}

get filePath() {
return this.#test.entryFile;
}

get fullName() {
return getFullName(this.#test);
}
Expand Down Expand Up @@ -343,6 +347,10 @@ class SuiteContext {
return this.#suite.name;
}

get filePath() {
return this.#suite.entryFile;
}

get fullName() {
return getFullName(this.#suite);
}
Expand All @@ -357,7 +365,7 @@ class Test extends AsyncResource {
super('Test');

let { fn, name, parent } = options;
const { concurrency, loc, only, timeout, todo, skip, signal, plan } = options;
const { concurrency, entryFile, loc, only, timeout, todo, skip, signal, plan } = options;

if (typeof fn !== 'function') {
fn = noop;
Expand Down Expand Up @@ -386,6 +394,7 @@ class Test extends AsyncResource {
this.runOnlySubtests = this.only;
this.childNumber = 0;
this.timeout = kDefaultTimeout;
this.entryFile = entryFile;
this.root = this;
this.hooks = {
__proto__: null,
Expand All @@ -406,6 +415,7 @@ class Test extends AsyncResource {
this.runOnlySubtests = !this.only;
this.childNumber = parent.subtests.length + 1;
this.timeout = parent.timeout;
this.entryFile = parent.entryFile;
this.root = parent.root;
this.hooks = {
__proto__: null,
Expand Down
52 changes: 52 additions & 0 deletions test/parallel/test-runner-test-filepath.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use strict';
require('../common');
const tmpdir = require('../common/tmpdir');
const { strictEqual } = require('node:assert');
const { writeFileSync } = require('node:fs');
const { suite, test } = require('node:test');

tmpdir.refresh();

suite('suite', (t) => {
strictEqual(t.filePath, __filename);

test('test', (t) => {
strictEqual(t.filePath, __filename);

t.test('subtest', (t) => {
strictEqual(t.filePath, __filename);

t.test('subsubtest', (t) => {
strictEqual(t.filePath, __filename);
});
});
});
});

test((t) => {
strictEqual(t.filePath, __filename);
});

const importedTestFile = tmpdir.resolve('temp.js');
writeFileSync(importedTestFile, `
'use strict';
const { strictEqual } = require('node:assert');
const { suite, test } = require('node:test');
suite('imported suite', (t) => {
strictEqual(t.filePath, ${JSON.stringify(__filename)});
test('imported test', (t) => {
strictEqual(t.filePath, ${JSON.stringify(__filename)});
t.test('imported subtest', (t) => {
strictEqual(t.filePath, ${JSON.stringify(__filename)});
t.test('imported subsubtest', (t) => {
strictEqual(t.filePath, ${JSON.stringify(__filename)});
});
});
});
});
`);
require(importedTestFile);

0 comments on commit 91f8ced

Please sign in to comment.