From 71e2dcf286932fce50c142e614c38b6cb1b9c5e6 Mon Sep 17 00:00:00 2001 From: Sylvester Keil Date: Sun, 15 Mar 2026 23:51:03 +0100 Subject: [PATCH 1/2] test_runner: use run() options with isolation="none" When using run() programatically with isolation="none", testNamePatterns, testSkipPattersn, and only were ignored. This combination of options only worked when set via CLI flags, because parseCommandLine() is still used to seed globalOptions. --- lib/internal/test_runner/runner.js | 13 ++++++ .../test-runner-isolation-none.mjs | 32 ++++++++++++++ test/parallel/test-runner-run.mjs | 42 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 test/fixtures/test-runner/test-runner-isolation-none.mjs diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index f90c7dcad10346..742ba64e53550d 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -784,6 +784,19 @@ function run(options = kEmptyObject) { cwd, globalSetupPath, }; + + if (isolation === 'none') { + if (testNamePatterns != null) { + globalOptions.testNamePatterns = testNamePatterns; + } + if (testSkipPatterns != null) { + globalOptions.testSkipPatterns = testSkipPatterns; + } + if (only != null) { + globalOptions.only = only; + } + } + const root = createTestTree(rootTestOptions, globalOptions); let testFiles = files ?? createTestFileList(globPatterns, cwd); const { isTestRunner } = globalOptions; diff --git a/test/fixtures/test-runner/test-runner-isolation-none.mjs b/test/fixtures/test-runner/test-runner-isolation-none.mjs new file mode 100644 index 00000000000000..03a32fd6ad5701 --- /dev/null +++ b/test/fixtures/test-runner/test-runner-isolation-none.mjs @@ -0,0 +1,32 @@ +import { run } from 'node:test'; +import { tap } from 'node:test/reporters'; +import { parseArgs } from 'node:util'; + +const { + values, +} = parseArgs({ + args: process.argv.slice(2), + options: { + file: { type: 'string' }, + only: { type: 'boolean' }, + 'name-pattern': { type: 'string' }, + 'skip-pattern': { type: 'string' }, + }, +}); + +const opts = { + isolation: 'none', + files: [values.file], +}; + +if (values.only) { + opts.only = true; +} +if (values['name-pattern']) { + opts.testNamePatterns = [new RegExp(values['name-pattern'])]; +} +if (values['skip-pattern']) { + opts.testSkipPatterns = [new RegExp(values['skip-pattern'])]; +} + +run(opts).compose(tap).pipe(process.stdout); \ No newline at end of file diff --git a/test/parallel/test-runner-run.mjs b/test/parallel/test-runner-run.mjs index e9bb6c4a260160..d14e1de9dc30ac 100644 --- a/test/parallel/test-runner-run.mjs +++ b/test/parallel/test-runner-run.mjs @@ -689,6 +689,48 @@ describe('forceExit', () => { }); }); +describe('with isolation="none"', () => { + const isolationNoneFixture = fixtures.path('test-runner', 'test-runner-isolation-none.mjs'); + + it('should pass only to children', { timeout: 10000 }, async () => { + const child = await common.spawnPromisified(process.execPath, [ + isolationNoneFixture, + '--file', join(testFixtures, 'test_only.js'), + '--only', + ]); + + assert.strictEqual(child.stderr, ''); + assert.strictEqual(child.code, 0); + assert.match(child.stdout, /ok 1 - this should be executed/); + assert.match(child.stdout, /# tests 1/); + }); + + it('should skip tests not matching testNamePatterns - RegExp', { timeout: 10000 }, async () => { + const child = await common.spawnPromisified(process.execPath, [ + isolationNoneFixture, + '--file', join(testFixtures, 'default-behavior/test/skip_by_name.cjs'), + '--name-pattern', 'executed', + ]); + + assert.strictEqual(child.stderr, ''); + assert.strictEqual(child.code, 0); + assert.match(child.stdout, /ok 1 - this should be executed/); + assert.match(child.stdout, /# tests 1/); + }); + + it('should skip tests matching testSkipPatterns - RegExp', { timeout: 10000 }, async () => { + const child = await common.spawnPromisified(process.execPath, [ + isolationNoneFixture, + '--file', join(testFixtures, 'default-behavior/test/skip_by_name.cjs'), + '--skip-pattern', 'skipped', + ]); + + assert.strictEqual(child.stderr, ''); + assert.strictEqual(child.code, 0); + assert.match(child.stdout, /ok 1 - this should be executed/); + assert.match(child.stdout, /# tests 1/); + }); +}); // exitHandler doesn't run until after the tests / after hooks finish. process.on('exit', () => { From 8637ae0a19cc48e4882bee4618cd0b6ff5a73f6c Mon Sep 17 00:00:00 2001 From: Sylvester Keil Date: Mon, 16 Mar 2026 00:26:43 +0100 Subject: [PATCH 2/2] Remove test timeouts --- test/parallel/test-runner-run.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/parallel/test-runner-run.mjs b/test/parallel/test-runner-run.mjs index d14e1de9dc30ac..17b75ad7806e28 100644 --- a/test/parallel/test-runner-run.mjs +++ b/test/parallel/test-runner-run.mjs @@ -692,7 +692,7 @@ describe('forceExit', () => { describe('with isolation="none"', () => { const isolationNoneFixture = fixtures.path('test-runner', 'test-runner-isolation-none.mjs'); - it('should pass only to children', { timeout: 10000 }, async () => { + it('should pass only to children', async () => { const child = await common.spawnPromisified(process.execPath, [ isolationNoneFixture, '--file', join(testFixtures, 'test_only.js'), @@ -705,7 +705,7 @@ describe('with isolation="none"', () => { assert.match(child.stdout, /# tests 1/); }); - it('should skip tests not matching testNamePatterns - RegExp', { timeout: 10000 }, async () => { + it('should skip tests not matching testNamePatterns - RegExp', async () => { const child = await common.spawnPromisified(process.execPath, [ isolationNoneFixture, '--file', join(testFixtures, 'default-behavior/test/skip_by_name.cjs'), @@ -718,7 +718,7 @@ describe('with isolation="none"', () => { assert.match(child.stdout, /# tests 1/); }); - it('should skip tests matching testSkipPatterns - RegExp', { timeout: 10000 }, async () => { + it('should skip tests matching testSkipPatterns - RegExp', async () => { const child = await common.spawnPromisified(process.execPath, [ isolationNoneFixture, '--file', join(testFixtures, 'default-behavior/test/skip_by_name.cjs'),