Skip to content

Commit

Permalink
test_runner: add cwd option and update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
pmarchini committed Aug 15, 2024
1 parent 2eb2916 commit f848750
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 15 deletions.
6 changes: 6 additions & 0 deletions doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,9 @@ added:
- v18.9.0
- v16.19.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/54225
description: Added the `cwd` option.
- version: v22.6.0
pr-url: https://github.com/nodejs/node/pull/53866
description: Added the `globPatterns` option.
Expand All @@ -1263,6 +1266,9 @@ changes:
parallel.
If `false`, it would only run one test file at a time.
**Default:** `false`.
* `cwd`: {string} Specifies the current working directory (cwd) to be used by the test runner.
The cwd serves as the base path for resolving files according to the [test runner execution model][].
**Default:** `process.cwd()`.
* `files`: {Array} An array containing the list of files to run.
**Default** matching files from [test runner execution model][].
* `forceExit`: {boolean} Configures the test runner to exit the process once
Expand Down
18 changes: 11 additions & 7 deletions lib/internal/test_runner/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const {
validateFunction,
validateObject,
validateInteger,
validateString,
} = require('internal/validators');
const { getInspectPort, isUsingInspector, isInspectorMessage } = require('internal/util/inspector');
const { isRegExp } = require('internal/util/types');
Expand Down Expand Up @@ -425,6 +426,9 @@ function watchFiles(testFiles, opts) {
const updatedTestFiles = createTestFileList(opts.globPatterns, opts.watchedDir);

const newFileName = ArrayPrototypeFind(updatedTestFiles, (x) => !ArrayPrototypeIncludes(testFiles, x));
const previousFileName = ArrayPrototypeFind(testFiles, (x) => !ArrayPrototypeIncludes(updatedTestFiles, x));

testFiles = updatedTestFiles;

// When file renamed (created / deleted) we need to update the watcher
if (newFileName) {
Expand All @@ -435,8 +439,6 @@ function watchFiles(testFiles, opts) {
if (!newFileName && previousFileName) {
return; // Avoid rerunning files when file deleted
}

testFiles = updatedTestFiles;
}

watcher.unfilterFilesOwnedBy(owners);
Expand Down Expand Up @@ -489,7 +491,7 @@ function run(options = kEmptyObject) {
setup,
only,
globPatterns,
cwd,
cwd = process.cwd(),
} = options;

if (files != null) {
Expand All @@ -514,6 +516,10 @@ function run(options = kEmptyObject) {
validateArray(globPatterns, 'options.globPatterns');
}

if (cwd != null) {
validateString(cwd, 'options.cwd');
}

if (globPatterns?.length > 0 && files?.length > 0) {
throw new ERR_INVALID_ARG_VALUE(
'options.globPatterns', globPatterns, 'is not supported when specifying \'options.files\'',
Expand Down Expand Up @@ -568,16 +574,14 @@ function run(options = kEmptyObject) {
});
}

const runCwd = cwd ?? process.cwd();

const root = createTestTree({ __proto__: null, concurrency, timeout, signal });

if (process.env.NODE_TEST_CONTEXT !== undefined) {
process.emitWarning('node:test run() is being called recursively within a test file. skipping running files.');
root.postRun();
return root.reporter;
}
let testFiles = files ?? createTestFileList(globPatterns, runCwd);
let testFiles = files ?? createTestFileList(globPatterns, cwd);

if (shard) {
testFiles = ArrayPrototypeFilter(testFiles, (_, index) => index % shard.total === shard.index - 1);
Expand All @@ -597,7 +601,7 @@ function run(options = kEmptyObject) {
globPatterns,
only,
forceExit,
watchedDir: runCwd,
watchedDir: cwd,
};
if (watch) {
filesWatcher = watchFiles(testFiles, opts);
Expand Down
9 changes: 5 additions & 4 deletions test/parallel/test-runner-run-watch.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ const test = require('node:test');
require('./dependency.js');
import('./dependency.mjs');
import('data:text/javascript,');
test('test has ran');`,
'test-without-dep.js': `
const test = require('node:test');
test('test has ran');`,
};

Expand Down Expand Up @@ -227,10 +224,14 @@ describe('test runner watch mode', () => {
});

it('should run new tests when a new file is created in a different cwd', async () => {
const newTestWithoutDep = `
const test = require('node:test');
test('test without dep has ran');
`;
const differentCwd = mkdtempSync(`${tmpdir.path}/different-cwd`);
const testFileName = 'test-without-dep.js';
const newTestFilePath = join(differentCwd, testFileName);
writeFileSync(newTestFilePath, fixtureContent[testFileName]);
writeFileSync(newTestFilePath, newTestWithoutDep);
const differentCwdTmpPath = basename(differentCwd);

await testWatch({
Expand Down
7 changes: 7 additions & 0 deletions test/parallel/test-runner-run.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,13 @@ describe('require(\'node:test\').run', { concurrency: true }, () => {
});
});

it('should only allow a string in options.cwd', async () => {
[Symbol(), {}, [], () => {}, 0, 1, 0n, 1n, true, false]
.forEach((cwd) => assert.throws(() => run({ cwd }), {
code: 'ERR_INVALID_ARG_TYPE'
}));
});

it('should only allow object as options', () => {
[Symbol(), [], () => {}, 0, 1, 0n, 1n, '', '1', true, false]
.forEach((options) => assert.throws(() => run(options), {
Expand Down
9 changes: 5 additions & 4 deletions test/parallel/test-runner-watch-mode.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ const test = require('node:test');
require('./dependency.js');
import('./dependency.mjs');
import('data:text/javascript,');
test('test has ran');`,
'test-without-dep.js': `
const test = require('node:test');
test('test has ran');`,
};

Expand Down Expand Up @@ -198,10 +195,14 @@ describe('test runner watch mode', () => {
});

it('should run new tests when a new file is created in a different cwd', async () => {
const newTestWithoutDep = `
const test = require('node:test');
test('test without dep has ran');
`;
const differentCwd = mkdtempSync(`${tmpdir.path}/different-cwd`);
const testFileName = 'test-without-dep.js';
const newTestFilePath = join(differentCwd, testFileName);
writeFileSync(newTestFilePath, fixtureContent[testFileName]);
writeFileSync(newTestFilePath, newTestWithoutDep);
const differentCwdTmpPath = basename(differentCwd);

await testWatch({
Expand Down

0 comments on commit f848750

Please sign in to comment.