diff --git a/test/fixtures/test-runner/source-map-line-lengths/index.js b/test/fixtures/test-runner/source-maps/line-lengths/index.js similarity index 100% rename from test/fixtures/test-runner/source-map-line-lengths/index.js rename to test/fixtures/test-runner/source-maps/line-lengths/index.js diff --git a/test/fixtures/test-runner/source-map-line-lengths/index.js.map b/test/fixtures/test-runner/source-maps/line-lengths/index.js.map similarity index 100% rename from test/fixtures/test-runner/source-map-line-lengths/index.js.map rename to test/fixtures/test-runner/source-maps/line-lengths/index.js.map diff --git a/test/fixtures/test-runner/source-map-line-lengths/index.ts b/test/fixtures/test-runner/source-maps/line-lengths/index.ts similarity index 100% rename from test/fixtures/test-runner/source-map-line-lengths/index.ts rename to test/fixtures/test-runner/source-maps/line-lengths/index.ts diff --git a/test/fixtures/test-runner/source-map-missing-sources/index.js b/test/fixtures/test-runner/source-maps/missing-sources/index.js similarity index 100% rename from test/fixtures/test-runner/source-map-missing-sources/index.js rename to test/fixtures/test-runner/source-maps/missing-sources/index.js diff --git a/test/fixtures/test-runner/source-map-missing-sources/index.js.map b/test/fixtures/test-runner/source-maps/missing-sources/index.js.map similarity index 100% rename from test/fixtures/test-runner/source-map-missing-sources/index.js.map rename to test/fixtures/test-runner/source-maps/missing-sources/index.js.map diff --git a/test/parallel/test-runner-coverage-source-map.js b/test/parallel/test-runner-coverage-source-map.js new file mode 100644 index 00000000000000..98752e757c542e --- /dev/null +++ b/test/parallel/test-runner-coverage-source-map.js @@ -0,0 +1,83 @@ +'use strict'; +const common = require('../common'); +const { pathToFileURL } = require('url'); +const fixtures = require('../common/fixtures'); +common.skipIfInspectorDisabled(); + +const { describe, it } = require('node:test'); + +function generateReport(report) { + report = ([ + '# start of coverage report', + ...report, + '# end of coverage report', + ]).join('\n'); + if (common.isWindows) { + report = report.replaceAll('/', '\\'); + } + return report; +} + +const flags = [ + '--test', '--experimental-test-coverage', '--test-reporter', 'tap', +]; + +describe('Coverage with source maps', async () => { + await it('should work with source maps', async (t) => { + const report = generateReport([ + '# --------------------------------------------------------------', + '# file | line % | branch % | funcs % | uncovered lines', + '# --------------------------------------------------------------', + '# a.test.ts | 53.85 | 100.00 | 100.00 | 8-13', // part of a bundle + '# b.test.ts | 55.56 | 100.00 | 100.00 | 1 7-9', // part of a bundle + '# index.test.js | 71.43 | 66.67 | 100.00 | 6-7', // no source map + '# stdin.test.ts | 57.14 | 100.00 | 100.00 | 4-6', // Source map without original file + '# --------------------------------------------------------------', + '# all files | 58.33 | 87.50 | 100.00 | ', + '# --------------------------------------------------------------', + ]); + + const spawned = await common.spawnPromisified(process.execPath, flags, { + cwd: fixtures.path('test-runner', 'coverage') + }); + t.assert.strictEqual(spawned.stderr, ''); + t.assert.ok(spawned.stdout.includes(report)); + t.assert.strictEqual(spawned.code, 1); + }); + + await it('properly accounts for line endings in source maps', async (t) => { + const report = generateReport([ + '# ------------------------------------------------------------------', + '# file | line % | branch % | funcs % | uncovered lines', + '# ------------------------------------------------------------------', + '# test | | | | ', + '# fixtures | | | | ', + '# test-runner | | | | ', + '# source-maps | | | | ', + '# line-lengths | | | | ', + '# index.ts | 100.00 | 100.00 | 100.00 | ', + '# ------------------------------------------------------------------', + '# all files | 100.00 | 100.00 | 100.00 | ', + '# ------------------------------------------------------------------', + ]); + + const spawned = await common.spawnPromisified(process.execPath, [ + ...flags, + fixtures.path('test-runner', 'source-maps', 'line-lengths', 'index.js'), + ]); + t.assert.strictEqual(spawned.stderr, ''); + t.assert.ok(spawned.stdout.includes(report)); + t.assert.strictEqual(spawned.code, 0); + }); + + await it('should throw when a source map is missing a source file', async (t) => { + const file = fixtures.path('test-runner', 'source-maps', 'missing-sources', 'index.js'); + const missing = fixtures.path('test-runner', 'source-maps', 'missing-sources', 'nonexistent.js'); + const spawned = await common.spawnPromisified(process.execPath, [...flags, file]); + + const error = `Cannot find '${pathToFileURL(missing)}' imported from the source map for '${pathToFileURL(file)}'`; + t.assert.strictEqual(spawned.stderr, ''); + t.assert.ok(spawned.stdout.includes(error)); + t.assert.strictEqual(spawned.code, 1); + }); +}).then(common.mustCall()); diff --git a/test/parallel/test-runner-coverage.js b/test/parallel/test-runner-coverage.js index 77e0afadbdff95..5756f1d237605c 100644 --- a/test/parallel/test-runner-coverage.js +++ b/test/parallel/test-runner-coverage.js @@ -6,7 +6,6 @@ const { readdirSync } = require('node:fs'); const { test } = require('node:test'); const fixtures = require('../common/fixtures'); const tmpdir = require('../common/tmpdir'); -const { pathToFileURL } = require('node:url'); const skipIfNoInspector = { skip: !process.features.inspector ? 'inspector disabled' : false }; @@ -290,51 +289,6 @@ test('coverage reports on lines, functions, and branches', skipIfNoInspector, as }); }); -test('coverage with source maps', skipIfNoInspector, () => { - let report = [ - '# start of coverage report', - '# --------------------------------------------------------------', - '# file | line % | branch % | funcs % | uncovered lines', - '# --------------------------------------------------------------', - '# a.test.ts | 53.85 | 100.00 | 100.00 | 8-13', // part of a bundle - '# b.test.ts | 55.56 | 100.00 | 100.00 | 1 7-9', // part of a bundle - '# index.test.js | 71.43 | 66.67 | 100.00 | 6-7', // no source map - '# stdin.test.ts | 57.14 | 100.00 | 100.00 | 4-6', // Source map without original file - '# --------------------------------------------------------------', - '# all files | 58.33 | 87.50 | 100.00 | ', - '# --------------------------------------------------------------', - '# end of coverage report', - ].join('\n'); - - if (common.isWindows) { - report = report.replaceAll('/', '\\'); - } - - const fixture = fixtures.path('test-runner', 'coverage'); - const args = [ - '--test', '--experimental-test-coverage', '--test-reporter', 'tap', - ]; - const result = spawnSync(process.execPath, args, { cwd: fixture }); - - assert.strictEqual(result.stderr.toString(), ''); - assert(result.stdout.toString().includes(report)); - assert.strictEqual(result.status, 1); -}); - -test('coverage with source maps missing sources', skipIfNoInspector, () => { - const file = fixtures.path('test-runner', 'source-map-missing-sources', 'index.js'); - const missing = fixtures.path('test-runner', 'source-map-missing-sources', 'nonexistent.js'); - const result = spawnSync(process.execPath, [ - '--test', - '--experimental-test-coverage', - file, - ]); - - const error = `Cannot find '${pathToFileURL(missing)}' imported from the source map for '${pathToFileURL(file)}'`; - assert(result.stdout.toString().includes(error)); - assert.strictEqual(result.status, 1); -}); - test('coverage with ESM hook - source irrelevant', skipIfNoInspector, () => { let report = [ '# start of coverage report', @@ -501,34 +455,6 @@ test('coverage with included and excluded files', skipIfNoInspector, () => { assert(!findCoverageFileForPid(result.pid)); }); -test('properly accounts for line endings in source maps', skipIfNoInspector, () => { - const fixture = fixtures.path('test-runner', 'source-map-line-lengths', 'index.js'); - const args = [ - '--test', '--experimental-test-coverage', '--test-reporter', 'tap', - fixture, - ]; - const report = [ - '# start of coverage report', - '# ----------------------------------------------------------------------------', - '# file | line % | branch % | funcs % | uncovered lines', - '# ----------------------------------------------------------------------------', - '# test | | | | ', - '# fixtures | | | | ', - '# test-runner | | | | ', - '# source-map-line-lengths | | | | ', - '# index.ts | 100.00 | 100.00 | 100.00 | ', - '# ----------------------------------------------------------------------------', - '# all files | 100.00 | 100.00 | 100.00 | ', - '# ----------------------------------------------------------------------------', - '# end of coverage report', - ].join('\n'); - - const result = spawnSync(process.execPath, args); - assert.strictEqual(result.stderr.toString(), ''); - assert(result.stdout.toString().includes(report)); - assert.strictEqual(result.status, 0); -}); - test('correctly prints the coverage report of files contained in parent directories', skipIfNoInspector, () => { let report = [ '# start of coverage report',