From 5b606770e39206b34e751f77bf76cc8c44809425 Mon Sep 17 00:00:00 2001 From: uditDewan Date: Mon, 14 Sep 2026 14:04:34 -0400 Subject: [PATCH] test_runner: do not name-filter test file wrappers Since run() applies testNamePatterns and testSkipPatterns to the root test configuration under isolation 'none', the file level test that wraps the single spawned process in watch mode is filtered by name itself. Its name is empty, so any name pattern filtered it out and no test ever ran. The same happens on the CLI with `--test --watch --test-isolation=none --test-name-pattern=...`. Exempt file wrappers from name filtering, as is already done for tag filtering: the patterns are applied to the tests inside of the file by the child process. Refs: https://github.com/nodejs/node/issues/64359 Refs: https://github.com/nodejs/node/pull/62269 Signed-off-by: uditDewan --- lib/internal/test_runner/runner.js | 6 ++++++ test/parallel/test-runner-run.mjs | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index 9434d232980c..ac9511642691 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -311,6 +311,12 @@ class FileTest extends Test { return false; } + willBeFilteredByName() { + // A FileTest represents a test file, not a named test. Name filters are + // applied to the tests inside of the file by the child process. + return false; + } + #skipReporting() { return this.#reportedChildren > 0 && (!this.error || this.error.failureType === kSubtestsFailed); } diff --git a/test/parallel/test-runner-run.mjs b/test/parallel/test-runner-run.mjs index d1d384a522e2..93affb76e03c 100644 --- a/test/parallel/test-runner-run.mjs +++ b/test/parallel/test-runner-run.mjs @@ -213,6 +213,28 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { assert.strictEqual(result[5], '# tests 1\n'); }); + it('should run tests with testNamePatterns in watch mode with isolation \'none\'', async () => { + // The name filters must not be applied to the file level test that wraps + // the spawned process. Without this, no test ever runs. + const controller = new AbortController(); + const passes = []; + const stream = run({ + files: [join(testFixtures, 'default-behavior/test/skip_by_name.cjs')], + watch: true, + isolation: 'none', + signal: controller.signal, + testNamePatterns: [/executed/], + }); + stream.on('test:pass', (event) => { + passes.push(event.name); + controller.abort(); + }); + // eslint-disable-next-line no-unused-vars + for await (const _ of stream); + assert.ok(passes.length > 0); + assert.ok(!passes.includes('this should be skipped')); + }); + it('should pass only to children', async () => { const result = await run({ files: [join(testFixtures, 'test_only.js')],