Skip to content

Commit a0cf638

Browse files
committed
test_runner: apply run() name filters with isolation none
The testNamePatterns and testSkipPatterns options of run() were only forwarded to spawned processes as CLI flags, so they were silently ignored when isolation was 'none' and tests ran in the current process. Apply the validated patterns to the root test configuration in that case. Exempt file level tests from name filtering: they represent test files rather than named tests, and filtering them prevented any test from running in watch mode when the root configuration contained name patterns. Fixes: #64359 Signed-off-by: uditDewan <udit.dewan21@gmail.com>
1 parent 0032189 commit a0cf638

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

lib/internal/test_runner/runner.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@ class FileTest extends Test {
284284
this.timeout = null;
285285
}
286286

287+
willBeFilteredByName() {
288+
// A FileTest represents a test file, not a named test. Name filters are
289+
// applied to the tests inside of the file by the child process.
290+
return false;
291+
}
292+
287293
#skipReporting() {
288294
return this.#reportedChildren > 0 && (!this.error || this.error.failureType === kSubtestsFailed);
289295
}
@@ -936,6 +942,15 @@ function run(options = kEmptyObject) {
936942
testTagFilters,
937943
};
938944

945+
if (isolation === 'none') {
946+
// Tests run in this process, so the name filters must be applied to the
947+
// root test's configuration. Under isolation 'process' the filters are
948+
// forwarded to each child process via --test-name-pattern and
949+
// --test-skip-pattern instead.
950+
globalOptions.testNamePatterns = testNamePatterns ?? globalOptions.testNamePatterns;
951+
globalOptions.testSkipPatterns = testSkipPatterns ?? globalOptions.testSkipPatterns;
952+
}
953+
939954
const root = createTestTree(rootTestOptions, globalOptions);
940955
let testFiles = files ?? createTestFileList(globPatterns, cwd);
941956
const { isTestRunner } = globalOptions;

test/parallel/test-runner-run.mjs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,43 @@ describe('require(\'node:test\').run', { concurrency: true }, () => {
213213
assert.strictEqual(result[5], '# tests 1\n');
214214
});
215215

216+
it('should apply testNamePatterns and testSkipPatterns with isolation \'none\'', async () => {
217+
const stream = run({
218+
files: [join(testFixtures, 'default-behavior/test/skip_by_name.cjs')],
219+
isolation: 'none',
220+
testNamePatterns: [/should/],
221+
testSkipPatterns: [/skipped/],
222+
});
223+
stream.on('test:fail', common.mustNotCall());
224+
stream.on('test:pass', common.mustCall((event) => {
225+
assert.strictEqual(event.name, 'this should be executed');
226+
}, 1));
227+
// eslint-disable-next-line no-unused-vars
228+
for await (const _ of stream);
229+
});
230+
231+
it('should run tests with testNamePatterns in watch mode with isolation \'none\'', async () => {
232+
// The name filters must not be applied to the file level test that wraps
233+
// the spawned process. Without this, no test ever runs.
234+
const controller = new AbortController();
235+
const passes = [];
236+
const stream = run({
237+
files: [join(testFixtures, 'default-behavior/test/skip_by_name.cjs')],
238+
watch: true,
239+
isolation: 'none',
240+
signal: controller.signal,
241+
testNamePatterns: [/executed/],
242+
});
243+
stream.on('test:pass', (event) => {
244+
passes.push(event.name);
245+
controller.abort();
246+
});
247+
// eslint-disable-next-line no-unused-vars
248+
for await (const _ of stream);
249+
assert.ok(passes.length > 0);
250+
assert.ok(!passes.includes('this should be skipped'));
251+
});
252+
216253
it('should pass only to children', async () => {
217254
const result = await run({
218255
files: [join(testFixtures, 'test_only.js')],

0 commit comments

Comments
 (0)