Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
test_runner: add context.filePath
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.
  • Loading branch information
cjihrig committed Jul 15, 2024
commit e5de45a4bfadedb500b3f447e5cc0e95727f58f9
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);