Skip to content

Commit ea70792

Browse files
committed
test_runner: fix watch cwd with isolation none
When watch mode runs with isolation disabled, spawn the child test runner with the files or glob patterns from the current run instead of reusing the parent process argv. This keeps discovery scoped to the configured cwd and avoids rerunning the driver test when the parent argv points outside that cwd. Fixes: #63689 Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5
1 parent be7ea27 commit ea70792

2 files changed

Lines changed: 49 additions & 2 deletions

File tree

lib/internal/test_runner/runner.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const {
1212
ArrayPrototypePush,
1313
ArrayPrototypePushApply,
1414
ArrayPrototypeShift,
15-
ArrayPrototypeSlice,
1615
ArrayPrototypeSome,
1716
ArrayPrototypeSort,
1817
MathMax,
@@ -185,6 +184,9 @@ function getRunArgs(path, { forceExit,
185184
testSkipPatterns,
186185
testTagFilterExpressions,
187186
only,
187+
hasFiles,
188+
testFiles,
189+
globPatterns,
188190
argv: suppliedArgs,
189191
execArgv,
190192
rerunFailuresFilePath,
@@ -245,7 +247,8 @@ function getRunArgs(path, { forceExit,
245247

246248
if (path === kIsolatedProcessName) {
247249
ArrayPrototypePush(runArgs, '--test');
248-
ArrayPrototypePushApply(runArgs, ArrayPrototypeSlice(process.argv, 1));
250+
ArrayPrototypePush(runArgs, '--test-isolation=none');
251+
ArrayPrototypePushApply(runArgs, hasFiles ? testFiles : globPatterns ?? []);
249252
} else {
250253
ArrayPrototypePush(runArgs, path);
251254
}
@@ -986,6 +989,7 @@ function run(options = kEmptyObject) {
986989
workerIdPool: isolation === 'process' ? workerIdPool : null,
987990
randomize,
988991
randomSeed,
992+
testFiles,
989993
};
990994

991995
if (isolation === 'process') {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Test run({ watch: true, cwd, isolation: 'none' }) does not reuse the
2+
// parent process argv when spawning the watch child.
3+
import * as common from '../common/index.mjs';
4+
import assert from 'node:assert';
5+
import { readFileSync, writeFileSync } from 'node:fs';
6+
import { join } from 'node:path';
7+
import { run } from 'node:test';
8+
import tmpdir from '../common/tmpdir.js';
9+
import { skipIfNoWatch } from '../common/watch.js';
10+
11+
skipIfNoWatch();
12+
tmpdir.refresh();
13+
14+
const marker = join(tmpdir.path, 'marker');
15+
writeFileSync(join(tmpdir.path, 'test.js'), `
16+
const test = require('node:test');
17+
const { writeFileSync } = require('node:fs');
18+
19+
test('test ran from cwd', () => {
20+
writeFileSync(${JSON.stringify(marker)}, 'ran');
21+
});
22+
`);
23+
24+
const controller = new AbortController();
25+
const stream = run({
26+
cwd: tmpdir.path,
27+
watch: true,
28+
signal: controller.signal,
29+
isolation: 'none',
30+
}).on('data', function({ type }) {
31+
if (type === 'test:watch:drained') {
32+
stream.removeAllListeners('test:fail');
33+
stream.removeAllListeners('test:pass');
34+
controller.abort();
35+
}
36+
});
37+
38+
stream.on('test:fail', common.mustNotCall());
39+
stream.on('test:pass', common.mustCall(1));
40+
// eslint-disable-next-line no-unused-vars
41+
for await (const _ of stream);
42+
43+
assert.strictEqual(readFileSync(marker, 'utf8'), 'ran');

0 commit comments

Comments
 (0)