Skip to content

Commit b77315a

Browse files
committed
test_runner: support custom arguments in run()
1 parent 812806a commit b77315a

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

doc/api/test.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,12 @@ changes:
12991299
* `setup` {Function} A function that accepts the `TestsStream` instance
13001300
and can be used to setup listeners before any tests are run.
13011301
**Default:** `undefined`.
1302+
* `execArgv` {Array} An array of CLI flags to pass to the `node` executable when
1303+
spawning the subprocesses. This option has no effect when `isolation` is `'none`'.
1304+
**Default:** `[]`
1305+
* `argv` {Array} An array of CLI flags to pass to each test file when spawning the
1306+
subprocesses. This option has no effect when `isolation` is `'none'`.
1307+
**Default:** `[]`.
13021308
* `signal` {AbortSignal} Allows aborting an in-progress test execution.
13031309
* `testNamePatterns` {string|RegExp|Array} A String, RegExp or a RegExp Array,
13041310
that can be used to only run tests whose name matches the provided pattern.

lib/internal/test_runner/runner.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,13 @@ function filterExecArgv(arg, i, arr) {
130130
!ArrayPrototypeSome(kFilterArgValues, (p) => arg === p || (i > 0 && arr[i - 1] === p) || StringPrototypeStartsWith(arg, `${p}=`));
131131
}
132132

133-
function getRunArgs(path, { forceExit, inspectPort, testNamePatterns, testSkipPatterns, only }) {
133+
function getRunArgs(path, { forceExit,
134+
inspectPort,
135+
testNamePatterns,
136+
testSkipPatterns,
137+
only,
138+
argv: suppliedArgs,
139+
execArgv }) {
134140
const argv = ArrayPrototypeFilter(process.execArgv, filterExecArgv);
135141
if (forceExit === true) {
136142
ArrayPrototypePush(argv, '--test-force-exit');
@@ -148,12 +154,20 @@ function getRunArgs(path, { forceExit, inspectPort, testNamePatterns, testSkipPa
148154
ArrayPrototypePush(argv, '--test-only');
149155
}
150156

157+
for (let i = 0; i < execArgv.length; i++) {
158+
ArrayPrototypePush(argv, execArgv[i]);
159+
}
160+
151161
if (path === kIsolatedProcessName) {
152162
ArrayPrototypePush(argv, '--test', ...ArrayPrototypeSlice(process.argv, 1));
153163
} else {
154164
ArrayPrototypePush(argv, path);
155165
}
156166

167+
for (let i = 0; i < suppliedArgs.length; i++) {
168+
ArrayPrototypePush(argv, suppliedArgs[i]);
169+
}
170+
157171
return argv;
158172
}
159173

@@ -548,6 +562,8 @@ function run(options = kEmptyObject) {
548562
lineCoverage = 0,
549563
branchCoverage = 0,
550564
functionCoverage = 0,
565+
execArgv = [],
566+
argv = [],
551567
} = options;
552568

553569
if (files != null) {
@@ -643,6 +659,9 @@ function run(options = kEmptyObject) {
643659
validateInteger(branchCoverage, 'options.branchCoverage', 0, 100);
644660
validateInteger(functionCoverage, 'options.functionCoverage', 0, 100);
645661

662+
validateStringArray(argv, 'options.argv');
663+
validateStringArray(execArgv, 'options.execArgv');
664+
646665
const rootTestOptions = { __proto__: null, concurrency, timeout, signal };
647666
const globalOptions = {
648667
__proto__: null,
@@ -685,6 +704,8 @@ function run(options = kEmptyObject) {
685704
forceExit,
686705
cwd,
687706
isolation,
707+
argv,
708+
execArgv,
688709
};
689710

690711
if (isolation === 'process') {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const { test } = require('node:test');
2+
3+
test('process.argv is setup', (t) => {
4+
t.assert.deepStrictEqual(process.argv.slice(2), ['--a-custom-argument']);
5+
});

test/parallel/test-runner-run.mjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ describe('require(\'node:test\').run', { concurrency: true }, () => {
3333
for await (const _ of stream);
3434
});
3535

36+
const argPrintingFile = join(testFixtures, 'print-arguments.js');
37+
it('should allow custom arguments via execArgv', async () => {
38+
const result = await run({ files: [argPrintingFile], execArgv: ['-p', '"Printed"'] }).compose(spec).toArray();
39+
assert.strictEqual(result[0].toString(), 'Printed\n');
40+
});
41+
42+
it('should allow custom arguments via argv', async () => {
43+
const stream = run({ files: [argPrintingFile], argv: ['--a-custom-argument'] });
44+
stream.on('test:fail', common.mustNotCall());
45+
stream.on('test:pass', common.mustCall(1));
46+
// eslint-disable-next-line no-unused-vars
47+
for await (const _ of stream);
48+
});
49+
3650
it('should run same file twice', async () => {
3751
const stream = run({
3852
files: [

0 commit comments

Comments
 (0)