diff --git a/test/fixtures/test-runner/index.test.js b/test/fixtures/test-runner/default-behavior/index.test.js similarity index 100% rename from test/fixtures/test-runner/index.test.js rename to test/fixtures/test-runner/default-behavior/index.test.js diff --git a/test/fixtures/test-runner/node_modules/test-nm.js b/test/fixtures/test-runner/default-behavior/node_modules/test-nm.js similarity index 100% rename from test/fixtures/test-runner/node_modules/test-nm.js rename to test/fixtures/test-runner/default-behavior/node_modules/test-nm.js diff --git a/test/fixtures/test-runner/random.test.mjs b/test/fixtures/test-runner/default-behavior/random.test.mjs similarity index 100% rename from test/fixtures/test-runner/random.test.mjs rename to test/fixtures/test-runner/default-behavior/random.test.mjs diff --git a/test/fixtures/test-runner/subdir/subdir_test.js b/test/fixtures/test-runner/default-behavior/subdir/subdir_test.js similarity index 100% rename from test/fixtures/test-runner/subdir/subdir_test.js rename to test/fixtures/test-runner/default-behavior/subdir/subdir_test.js diff --git a/test/fixtures/test-runner/test/random.cjs b/test/fixtures/test-runner/default-behavior/test/random.cjs similarity index 100% rename from test/fixtures/test-runner/test/random.cjs rename to test/fixtures/test-runner/default-behavior/test/random.cjs diff --git a/test/fixtures/test-runner/test/skip_by_name.cjs b/test/fixtures/test-runner/default-behavior/test/skip_by_name.cjs similarity index 100% rename from test/fixtures/test-runner/test/skip_by_name.cjs rename to test/fixtures/test-runner/default-behavior/test/skip_by_name.cjs diff --git a/test/parallel/test-runner-cli.js b/test/parallel/test-runner-cli.js index 496f53e23ea3a6..9401401aa9f09d 100644 --- a/test/parallel/test-runner-cli.js +++ b/test/parallel/test-runner-cli.js @@ -22,8 +22,8 @@ const testFixtures = fixtures.path('test-runner'); { // Default behavior. node_modules is ignored. Files that don't match the // pattern are ignored except in test/ directories. - const args = ['--test', testFixtures]; - const child = spawnSync(process.execPath, args); + const args = ['--test']; + const child = spawnSync(process.execPath, args, { cwd: join(testFixtures, 'default-behavior') }); assert.strictEqual(child.status, 1); assert.strictEqual(child.signal, null); @@ -39,8 +39,8 @@ const testFixtures = fixtures.path('test-runner'); { // Same but with a prototype mutation in require scripts. - const args = ['--require', join(testFixtures, 'protoMutation.js'), '--test', testFixtures]; - const child = spawnSync(process.execPath, args); + const args = ['--require', join(testFixtures, 'protoMutation.js'), '--test']; + const child = spawnSync(process.execPath, args, { cwd: join(testFixtures, 'default-behavior') }); const stdout = child.stdout.toString(); assert.match(stdout, /ok 1 - this should pass/); @@ -72,7 +72,7 @@ const testFixtures = fixtures.path('test-runner'); { // Searches node_modules if specified. - const args = ['--test', join(testFixtures, 'node_modules')]; + const args = ['--test', join(testFixtures, 'default-behavior/node_modules')]; const child = spawnSync(process.execPath, args); assert.strictEqual(child.status, 1); @@ -85,7 +85,7 @@ const testFixtures = fixtures.path('test-runner'); { // The current directory is used by default. const args = ['--test']; - const options = { cwd: testFixtures }; + const options = { cwd: join(testFixtures, 'default-behavior') }; const child = spawnSync(process.execPath, args, options); assert.strictEqual(child.status, 1); @@ -124,7 +124,7 @@ const testFixtures = fixtures.path('test-runner'); // Test combined stream outputs const args = [ '--test', - 'test/fixtures/test-runner/index.test.js', + 'test/fixtures/test-runner/default-behavior/index.test.js', 'test/fixtures/test-runner/nested.js', 'test/fixtures/test-runner/invalid-tap.js', ]; @@ -202,7 +202,7 @@ const testFixtures = fixtures.path('test-runner'); const args = ['--no-warnings', '--experimental-loader', 'data:text/javascript,', '--require', fixtures.path('empty.js'), - '--test', join(testFixtures, 'index.test.js')]; + '--test', join(testFixtures, 'default-behavior', 'index.test.js')]; const child = spawnSync(process.execPath, args); assert.strictEqual(child.stderr.toString(), ''); diff --git a/test/parallel/test-runner-exit-code.js b/test/parallel/test-runner-exit-code.js index d177ec438bdd45..8eeebc21d31753 100644 --- a/test/parallel/test-runner-exit-code.js +++ b/test/parallel/test-runner-exit-code.js @@ -43,7 +43,10 @@ if (process.argv[2] === 'child') { assert.strictEqual(child.status, 0); assert.strictEqual(child.signal, null); - child = spawnSync(process.execPath, ['--test', fixtures.path('test-runner', 'subdir', 'subdir_test.js')]); + child = spawnSync(process.execPath, [ + '--test', + fixtures.path('test-runner', 'default-behavior', 'subdir', 'subdir_test.js'), + ]); assert.strictEqual(child.status, 0); assert.strictEqual(child.signal, null); diff --git a/test/parallel/test-runner-inspect.mjs b/test/parallel/test-runner-inspect.mjs index bdff1ce7ceb84f..20c4cdf354451b 100644 --- a/test/parallel/test-runner-inspect.mjs +++ b/test/parallel/test-runner-inspect.mjs @@ -11,7 +11,11 @@ common.skipIfInspectorDisabled(); tmpdir.refresh(); { - const child = new NodeInstance(['--test', '--inspect-brk=0'], undefined, fixtures.path('test-runner/index.test.js')); + const child = new NodeInstance( + ['--test', '--inspect-brk=0'], + undefined, + fixtures.path('test-runner/default-behavior/index.test.js') + ); let stdout = ''; let stderr = ''; diff --git a/test/parallel/test-runner-run.mjs b/test/parallel/test-runner-run.mjs index b5c41b8ae925de..aebc1b74fead9b 100644 --- a/test/parallel/test-runner-run.mjs +++ b/test/parallel/test-runner-run.mjs @@ -26,7 +26,7 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should succeed with a file', async () => { - const stream = run({ files: [join(testFixtures, 'test/random.cjs')] }); + const stream = run({ files: [join(testFixtures, 'default-behavior/test/random.cjs')] }); stream.on('test:fail', common.mustNotCall()); stream.on('test:pass', common.mustCall(1)); // eslint-disable-next-line no-unused-vars @@ -34,7 +34,12 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should run same file twice', async () => { - const stream = run({ files: [join(testFixtures, 'test/random.cjs'), join(testFixtures, 'test/random.cjs')] }); + const stream = run({ + files: [ + join(testFixtures, 'default-behavior/test/random.cjs'), + join(testFixtures, 'default-behavior/test/random.cjs'), + ] + }); stream.on('test:fail', common.mustNotCall()); stream.on('test:pass', common.mustCall(2)); // eslint-disable-next-line no-unused-vars @@ -68,7 +73,9 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should be piped with dot', async () => { - const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(dot).toArray(); + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')] + }).compose(dot).toArray(); assert.deepStrictEqual(result, [ '.', '\n', @@ -77,7 +84,9 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { it('should be piped with spec', async () => { const specReporter = new spec(); - const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(specReporter).toArray(); + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')] + }).compose(specReporter).toArray(); const stringResults = result.map((bfr) => bfr.toString()); assert.match(stringResults[0], /this should pass/); assert.match(stringResults[1], /tests 1/); @@ -85,7 +94,9 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should be piped with tap', async () => { - const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(tap).toArray(); + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')] + }).compose(tap).toArray(); assert.strictEqual(result.length, 13); assert.strictEqual(result[0], 'TAP version 13\n'); assert.strictEqual(result[1], '# Subtest: this should pass\n'); @@ -103,7 +114,10 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should skip tests not matching testNamePatterns - RegExp', async () => { - const result = await run({ files: [join(testFixtures, 'test/skip_by_name.cjs')], testNamePatterns: [/executed/] }) + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/skip_by_name.cjs')], + testNamePatterns: [/executed/] + }) .compose(tap) .toArray(); assert.strictEqual(result[2], 'ok 1 - this should be skipped # SKIP test name does not match pattern\n'); @@ -111,16 +125,37 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should skip tests not matching testNamePatterns - string', async () => { - const result = await run({ files: [join(testFixtures, 'test/skip_by_name.cjs')], testNamePatterns: ['executed'] }) + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/skip_by_name.cjs')], + testNamePatterns: ['executed'] + }) .compose(tap) .toArray(); assert.strictEqual(result[2], 'ok 1 - this should be skipped # SKIP test name does not match pattern\n'); assert.strictEqual(result[5], 'ok 2 - this should be executed\n'); }); - it('should stop watch mode when abortSignal aborts', async () => { + it('should emit "test:watch:drained" event on watch mode', async () => { const controller = new AbortController(); - const result = await run({ files: [join(testFixtures, 'test/random.cjs')], watch: true, signal: controller.signal }) + await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')], + watch: true, + signal: controller.signal, + }).on('data', function({ type }) { + if (type === 'test:watch:drained') { + controller.abort(); + } + }); + }); + + describe('AbortSignal', () => { + it('should stop watch mode when abortSignal aborts', async () => { + const controller = new AbortController(); + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')], + watch: true, + signal: controller.signal + }) .compose(async function* (source) { for await (const chunk of source) { if (chunk.type === 'test:pass') { @@ -130,17 +165,74 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { } }) .toArray(); - assert.deepStrictEqual(result, ['this should pass']); - }); + assert.deepStrictEqual(result, ['this should pass']); + }); - it('should emit "test:watch:drained" event on watch mode', async () => { - const controller = new AbortController(); - await run({ files: [join(testFixtures, 'test/random.cjs')], watch: true, signal: controller.signal }) - .on('data', function({ type }) { - if (type === 'test:watch:drained') { - controller.abort(); + it('should abort when test succeeded', async () => { + const stream = run({ + files: [ + fixtures.path( + 'test-runner', + 'aborts', + 'successful-test-still-call-abort.js' + ), + ], + }); + + let passedTestCount = 0; + let failedTestCount = 0; + + let output = ''; + for await (const data of stream) { + if (data.type === 'test:stdout') { + output += data.data.message.toString(); } + if (data.type === 'test:fail') { + failedTestCount++; + } + if (data.type === 'test:pass') { + passedTestCount++; + } + } + + assert.match(output, /abort called for test 1/); + assert.match(output, /abort called for test 2/); + assert.strictEqual(failedTestCount, 0, new Error('no tests should fail')); + assert.strictEqual(passedTestCount, 2); + }); + + it('should abort when test failed', async () => { + const stream = run({ + files: [ + fixtures.path( + 'test-runner', + 'aborts', + 'failed-test-still-call-abort.js' + ), + ], }); + + let passedTestCount = 0; + let failedTestCount = 0; + + let output = ''; + for await (const data of stream) { + if (data.type === 'test:stdout') { + output += data.data.message.toString(); + } + if (data.type === 'test:fail') { + failedTestCount++; + } + if (data.type === 'test:pass') { + passedTestCount++; + } + } + + assert.match(output, /abort called for test 1/); + assert.match(output, /abort called for test 2/); + assert.strictEqual(passedTestCount, 0, new Error('no tests should pass')); + assert.strictEqual(failedTestCount, 2); + }); }); describe('sharding', () => {