Skip to content

Commit 3a42085

Browse files
authored
test_runner: ignore unmapped lines for coverage
PR-URL: #55228 Refs: #55106 Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
1 parent 5a3da7b commit 3a42085

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

lib/internal/test_runner/coverage.js

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22
const {
33
ArrayFrom,
4+
ArrayPrototypeForEach,
45
ArrayPrototypeMap,
56
ArrayPrototypePush,
67
JSONParse,
@@ -57,12 +58,21 @@ class CoverageLine {
5758
}
5859

5960
class TestCoverage {
60-
constructor(coverageDirectory, originalCoverageDirectory, workingDirectory, excludeGlobs, includeGlobs, thresholds) {
61+
constructor(
62+
coverageDirectory,
63+
originalCoverageDirectory,
64+
workingDirectory,
65+
excludeGlobs,
66+
includeGlobs,
67+
sourceMaps,
68+
thresholds,
69+
) {
6170
this.coverageDirectory = coverageDirectory;
6271
this.originalCoverageDirectory = originalCoverageDirectory;
6372
this.workingDirectory = workingDirectory;
6473
this.excludeGlobs = excludeGlobs;
6574
this.includeGlobs = includeGlobs;
75+
this.sourceMaps = sourceMaps;
6676
this.thresholds = thresholds;
6777
}
6878

@@ -366,7 +376,13 @@ class TestCoverage {
366376
this.getLines(data.sources[j], data.sourcesContent[j]);
367377
}
368378
}
379+
369380
const sourceMap = new SourceMap(data, { __proto__: null, lineLengths });
381+
const linesToCover = new SafeSet();
382+
383+
for (let i = 0; i < sourceMap[kMappings].length; i++) {
384+
linesToCover.add(sourceMap[kMappings][i][3] + 1);
385+
}
370386

371387
for (let j = 0; j < functions.length; ++j) {
372388
const { ranges, functionName, isBlockCoverage } = functions[j];
@@ -415,6 +431,15 @@ class TestCoverage {
415431
// No mappable ranges. Skip the function.
416432
continue;
417433
}
434+
435+
if (this.sourceMaps) {
436+
ArrayPrototypeForEach(this.getLines(newUrl), (mappedLine) => {
437+
if (!linesToCover.has(mappedLine.line)) {
438+
mappedLine.ignore = true;
439+
}
440+
});
441+
}
442+
418443
const newScript = newResult.get(newUrl) ?? { __proto__: null, url: newUrl, functions: [] };
419444
ArrayPrototypePush(newScript.functions, { __proto__: null, functionName, ranges: newRanges, isBlockCoverage });
420445
newResult.set(newUrl, newScript);
@@ -516,6 +541,7 @@ function setupCoverage(options) {
516541
options.cwd,
517542
options.coverageExcludeGlobs,
518543
options.coverageIncludeGlobs,
544+
options.sourceMaps,
519545
{
520546
__proto__: null,
521547
line: options.lineCoverage,

test/parallel/test-runner-coverage-source-map.js

+26
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,31 @@ describe('Coverage with source maps', async () => {
4545
t.assert.strictEqual(spawned.code, 1);
4646
});
4747

48+
it('accounts only mapped lines when --enable-source-maps is provided', async (t) => {
49+
const report = generateReport([
50+
'# --------------------------------------------------------------',
51+
'# file | line % | branch % | funcs % | uncovered lines',
52+
'# --------------------------------------------------------------',
53+
'# a.test.ts | 100.00 | 100.00 | 100.00 | ', // part of a bundle
54+
'# b.test.ts | 88.89 | 100.00 | 100.00 | 1', // part of a bundle
55+
'# index.test.js | 71.43 | 66.67 | 100.00 | 6-7', // no source map
56+
'# stdin.test.ts | 100.00 | 100.00 | 100.00 | ', // Source map without original file
57+
'# --------------------------------------------------------------',
58+
'# all files | 91.67 | 87.50 | 100.00 | ',
59+
'# --------------------------------------------------------------',
60+
]);
61+
62+
const spawned = await common.spawnPromisified(process.execPath, [
63+
'--test', '--experimental-test-coverage', '--enable-source-maps', '--test-reporter', 'tap',
64+
], {
65+
cwd: fixtures.path('test-runner', 'coverage')
66+
});
67+
68+
t.assert.strictEqual(spawned.stderr, '');
69+
t.assert.ok(spawned.stdout.includes(report));
70+
t.assert.strictEqual(spawned.code, 1);
71+
});
72+
4873
await it('properly accounts for line endings in source maps', async (t) => {
4974
const report = generateReport([
5075
'# ------------------------------------------------------------------',
@@ -89,6 +114,7 @@ describe('Coverage with source maps', async () => {
89114
const spawned = await common.spawnPromisified(process.execPath, [...flags, file]);
90115

91116
const error = `The source map for '${pathToFileURL(file)}' does not exist or is corrupt`;
117+
92118
t.assert.strictEqual(spawned.stderr, '');
93119
t.assert.ok(spawned.stdout.includes(error));
94120
t.assert.strictEqual(spawned.code, 1);

0 commit comments

Comments
 (0)