Skip to content

Commit 694ee5e

Browse files
committed
test_runner: code coverage files tree view
1 parent 348a858 commit 694ee5e

9 files changed

+164
-122
lines changed

lib/internal/test_runner/utils.js

Lines changed: 68 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
'use strict';
22
const {
33
ArrayPrototypeFlatMap,
4+
ArrayPrototypeForEach,
45
ArrayPrototypeJoin,
56
ArrayPrototypeMap,
67
ArrayPrototypePush,
78
ArrayPrototypeReduce,
89
ArrayPrototypeSome,
9-
MathFloor,
1010
MathMax,
1111
MathMin,
1212
NumberParseInt,
@@ -406,6 +406,32 @@ const kColumns = ['line %', 'branch %', 'funcs %'];
406406
const kColumnsKeys = ['coveredLinePercent', 'coveredBranchPercent', 'coveredFunctionPercent'];
407407
const kSeparator = ' | ';
408408

409+
function buildFileTree(summary) {
410+
const tree = { __proto__: null };
411+
let treeDepth = 0;
412+
let longestFile = 0;
413+
414+
ArrayPrototypeForEach(summary.files, (file) => {
415+
const parts = relative(summary.workingDirectory, file.path).split('/');
416+
let current = tree;
417+
ArrayPrototypeForEach(parts, (part, index) => {
418+
if (!current[part]) {
419+
current[part] = { __proto__: null };
420+
}
421+
current = current[part];
422+
// If this is the last part, add the file to the tree
423+
if (index === parts.length - 1) {
424+
current.file = file;
425+
current.finalPath = parts;
426+
}
427+
});
428+
treeDepth = MathMax(treeDepth, parts.length);
429+
longestFile = MathMax(longestFile, ...parts.map((part) => part.length));
430+
});
431+
432+
return { __proto__: null, tree, treeDepth, longestFile };
433+
}
434+
409435
function getCoverageReport(pad, summary, symbol, color, table) {
410436
const prefix = `${pad}${symbol}`;
411437
let report = `${color}${prefix}start of coverage report\n`;
@@ -415,10 +441,15 @@ function getCoverageReport(pad, summary, symbol, color, table) {
415441
let uncoveredLinesPadLength;
416442
let tableWidth;
417443

444+
// Create a tree of file paths
445+
const { tree, treeDepth, longestFile } = buildFileTree(summary);
446+
418447
if (table) {
419-
// Get expected column sizes
420-
filePadLength = table && ArrayPrototypeReduce(summary.files, (acc, file) =>
421-
MathMax(acc, relative(summary.workingDirectory, file.path).length), 0);
448+
// Calculate expected column sizes based on the tree
449+
// Every level of the tree adds 2 to the column size + the longest file name
450+
filePadLength = table && longestFile;
451+
filePadLength += 2 * treeDepth;
452+
// Get the maximum length of the file path or 'file'
422453
filePadLength = MathMax(filePadLength, 'file'.length);
423454
const fileWidth = filePadLength + 2;
424455

@@ -437,9 +468,7 @@ function getCoverageReport(pad, summary, symbol, color, table) {
437468
const columnsExtras = tableWidth - availableWidth;
438469
if (table && columnsExtras > 0) {
439470
// Ensure file name is sufficiently visible
440-
const minFilePad = MathMin(8, filePadLength);
441-
filePadLength -= MathFloor(columnsExtras * 0.2);
442-
filePadLength = MathMax(filePadLength, minFilePad);
471+
filePadLength = MathMin(availableWidth * 0.5, filePadLength);
443472

444473
// Get rest of available space, subtracting margins
445474
uncoveredLinesPadLength = MathMax(availableWidth - columnsWidth - (filePadLength + 2) - 2, 1);
@@ -465,75 +494,49 @@ function getCoverageReport(pad, summary, symbol, color, table) {
465494
return result;
466495
}
467496

468-
function getfilePathMultiline(string, width, pad, coverage) {
469-
if (!table) return string;
470-
471-
const lines = [];
472-
let currentLine = '';
473-
474-
for (const word of StringPrototypeSplit(string, '\\')) {
475-
if (currentLine.length + word.length + 1 <= width) {
476-
// If adding the next word fits in the current line, append it
477-
currentLine += (currentLine.length > 0 ? '\\' : '') + word;
478-
} else {
479-
// If adding the next word exceeds the width, start a new line
480-
ArrayPrototypePush(lines, currentLine);
481-
currentLine = word;
482-
}
483-
}
484-
485-
// Add the last line if any
486-
if (currentLine.length > 0) {
487-
ArrayPrototypePush(lines, currentLine);
488-
}
489-
490-
const truncatedLines = ArrayPrototypeMap(lines, (line) => StringPrototypeSlice(line, 0, width));
491-
492-
// Delete empty lines if any
493-
for (let i = 0; i < truncatedLines.length; ++i) {
494-
if (truncatedLines[i].length === 0) {
495-
truncatedLines.splice(i, 1);
496-
}
497-
}
498-
499-
return getCell(
500-
ArrayPrototypeJoin(truncatedLines, '\n'),
501-
width,
502-
pad,
503-
false,
504-
coverage,
505-
);
506-
}
507-
508497
// Head
509498
if (table) report += addTableLine(prefix, tableWidth);
510499
report += `${prefix}${getCell('file', filePadLength, StringPrototypePadEnd, truncateEnd)}${kSeparator}` +
511-
`${ArrayPrototypeJoin(ArrayPrototypeMap(kColumns, (column, i) => getCell(column, columnPadLengths[i], StringPrototypePadStart)), kSeparator)}${kSeparator}` +
512-
`${getCell('uncovered lines', uncoveredLinesPadLength, false, truncateEnd)}\n`;
500+
`${ArrayPrototypeJoin(ArrayPrototypeMap(kColumns, (column, i) => getCell(column, columnPadLengths[i], StringPrototypePadStart)), kSeparator)}${kSeparator}` +
501+
`${getCell('uncovered lines', uncoveredLinesPadLength, false, truncateEnd)}\n`;
513502
if (table) report += addTableLine(prefix, tableWidth);
514503

515-
// Body
516-
for (let i = 0; i < summary.files.length; ++i) {
517-
const file = summary.files[i];
518-
const relativePath = relative(summary.workingDirectory, file.path);
519-
520-
let fileCoverage = 0;
521-
const coverages = ArrayPrototypeMap(kColumnsKeys, (columnKey) => {
522-
const percent = file[columnKey];
523-
fileCoverage += percent;
524-
return percent;
525-
});
526-
fileCoverage /= kColumnsKeys.length;
504+
// Body using the tree
505+
function printTree(tree, depth) {
506+
for (const key in tree) {
507+
if (tree[key].file) {
508+
const file = tree[key].file;
509+
const fileName = file.path.split('/').pop();
510+
511+
let fileCoverage = 0;
512+
const coverages = ArrayPrototypeMap(kColumnsKeys, (columnKey) => {
513+
const percent = file[columnKey];
514+
fileCoverage += percent;
515+
return percent;
516+
});
517+
fileCoverage /= kColumnsKeys.length;
518+
519+
report += `${prefix}${StringPrototypeRepeat(' ', depth)}${getCell(fileName, filePadLength - depth, StringPrototypePadEnd, false, fileCoverage)}${kSeparator}` +
520+
`${ArrayPrototypeJoin(ArrayPrototypeMap(coverages, (coverage, j) => getCell(NumberPrototypeToFixed(coverage, 2), columnPadLengths[j], StringPrototypePadStart, false, coverage)), kSeparator)}${kSeparator}` +
521+
`${getCell(formatUncoveredLines(getUncoveredLines(file.lines), table), uncoveredLinesPadLength, false, truncateEnd)}\n`;
522+
} else {
523+
// Print a line for the directory with empty columns
524+
report += `${prefix}${StringPrototypeRepeat(' ', depth)}${getCell(key, filePadLength - depth, StringPrototypePadEnd, false)}${kSeparator}` +
525+
`${ArrayPrototypeJoin(ArrayPrototypeMap(columnPadLengths, (columnPadLength) => getCell('', columnPadLength, StringPrototypePadStart, false)), kSeparator)}${kSeparator}` +
526+
`${getCell('', uncoveredLinesPadLength, false, truncateEnd)}\n`;
527527

528-
report += `${prefix}${getfilePathMultiline(relativePath, filePadLength, StringPrototypePadEnd, fileCoverage)}${kSeparator}` +
529-
`${ArrayPrototypeJoin(ArrayPrototypeMap(coverages, (coverage, j) => getCell(NumberPrototypeToFixed(coverage, 2), columnPadLengths[j], StringPrototypePadStart, false, coverage)), kSeparator)}${kSeparator}` +
530-
`${getCell(formatUncoveredLines(getUncoveredLines(file.lines), table), uncoveredLinesPadLength, false, truncateEnd)}\n`;
528+
// Continue printing the tree recursively
529+
printTree(tree[key], depth + 1);
530+
}
531+
}
531532
}
533+
printTree(tree, 0);
534+
532535

533536
// Foot
534537
if (table) report += addTableLine(prefix, tableWidth);
535538
report += `${prefix}${getCell('all files', filePadLength, StringPrototypePadEnd, truncateEnd)}${kSeparator}` +
536-
`${ArrayPrototypeJoin(ArrayPrototypeMap(kColumnsKeys, (columnKey, j) => getCell(NumberPrototypeToFixed(summary.totals[columnKey], 2), columnPadLengths[j], StringPrototypePadStart, false, summary.totals[columnKey])), kSeparator)} |\n`;
539+
`${ArrayPrototypeJoin(ArrayPrototypeMap(kColumnsKeys, (columnKey, j) => getCell(NumberPrototypeToFixed(summary.totals[columnKey], 2), columnPadLengths[j], StringPrototypePadStart, false, summary.totals[columnKey])), kSeparator)} |\n`;
537540
if (table) report += addTableLine(prefix, tableWidth);
538541

539542
report += `${prefix}end of coverage report\n`;
@@ -542,7 +545,6 @@ function getCoverageReport(pad, summary, symbol, color, table) {
542545
}
543546
return report;
544547
}
545-
546548
module.exports = {
547549
convertStringToRegExp,
548550
countCompletedTest,

test/fixtures/test-runner/output/coverage-width-100-uncovered-lines.snapshot

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@ ok 1 - Coverage Print Fixed Width 100
1515
# duration_ms *
1616
# start of coverage report
1717
# --------------------------------------------------------------------------------------------------
18-
# file | line % | branch % | funcs % | uncovered lines
18+
# file | line % | branch % | funcs % | uncovered lines
1919
# --------------------------------------------------------------------------------------------------
20-
# …ap/a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
21-
# …ap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
22-
# …ines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52 55-57 59-6…
23-
# …nes.mjs | 100.00 | 100.00 | 100.00 |
20+
# test | | | |
21+
# fixtures | | | |
22+
# test-runner | | | |
23+
# coverage-snap | | | |
24+
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 …
25+
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
26+
# many-uncovered-lines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 …
27+
# output | | | |
28+
# coverage-width-100-uncovered-lines.mjs | 100.00 | 100.00 | 100.00 |
2429
# --------------------------------------------------------------------------------------------------
25-
# all fil… | 52.80 | 60.00 | 1.61 |
30+
# all files | 52.80 | 60.00 | 1.61 |
2631
# --------------------------------------------------------------------------------------------------
2732
# end of coverage report

test/fixtures/test-runner/output/coverage-width-100.snapshot

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@ ok 1 - Coverage Print Fixed Width 100
1515
# duration_ms *
1616
# start of coverage report
1717
# --------------------------------------------------------------------------------------------------
18-
# file | line % | branch % | funcs % | uncovered lines
18+
# file | line % | branch % | funcs % | uncovered lines
1919
# --------------------------------------------------------------------------------------------------
20-
# test/fixtures/test-runner/coverage-snap/a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 …
21-
# test/fixtures/test-runner/coverage-snap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
22-
# …tures/test-runner/output/coverage-width-100.mjs | 100.00 | 100.00 | 100.00 |
20+
# test | | | |
21+
# fixtures | | | |
22+
# test-runner | | | |
23+
# coverage-snap | | | |
24+
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-4…
25+
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
26+
# output | | | |
27+
# coverage-width-100.mjs | 100.00 | 100.00 | 100.00 |
2328
# --------------------------------------------------------------------------------------------------
24-
# all files | 60.81 | 100.00 | 0.00 |
29+
# all files | 60.81 | 100.00 | 0.00 |
2530
# --------------------------------------------------------------------------------------------------
2631
# end of coverage report

test/fixtures/test-runner/output/coverage-width-150-uncovered-lines.snapshot

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@ ok 1 - Coverage Print Fixed Width 150
1515
# duration_ms *
1616
# start of coverage report
1717
# ----------------------------------------------------------------------------------------------------------------------------------------------------
18-
# file | line % | branch % | funcs % | uncovered lines
18+
# file | line % | branch % | funcs % | uncovered lines
1919
# ----------------------------------------------------------------------------------------------------------------------------------------------------
20-
# …ap/a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
21-
# …ap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
22-
# …ines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52 55-57 59-61 63-65 67-69 91-93 96-98 100-102 104-106 111-112 …
23-
# …nes.mjs | 100.00 | 100.00 | 100.00 |
20+
# test | | | |
21+
# fixtures | | | |
22+
# test-runner | | | |
23+
# coverage-snap | | | |
24+
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
25+
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
26+
# many-uncovered-lines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52 55-57 59-61 63-65 67…
27+
# output | | | |
28+
# coverage-width-150-uncovered-lines.mjs | 100.00 | 100.00 | 100.00 |
2429
# ----------------------------------------------------------------------------------------------------------------------------------------------------
25-
# all fil… | 52.80 | 60.00 | 1.61 |
30+
# all files | 52.80 | 60.00 | 1.61 |
2631
# ----------------------------------------------------------------------------------------------------------------------------------------------------
2732
# end of coverage report

test/fixtures/test-runner/output/coverage-width-150.snapshot

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@ ok 1 - Coverage Print Fixed Width 150
1414
# todo 0
1515
# duration_ms *
1616
# start of coverage report
17-
# -------------------------------------------------------------------------------------------------------------------------------------
18-
# file | line % | branch % | funcs % | uncovered lines
19-
# -------------------------------------------------------------------------------------------------------------------------------------
20-
# test/fixtures/test-runner/coverage-snap/a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
21-
# test/fixtures/test-runner/coverage-snap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
22-
# test/fixtures/test-runner/output/coverage-width-150.mjs | 100.00 | 100.00 | 100.00 |
23-
# -------------------------------------------------------------------------------------------------------------------------------------
24-
# all files | 60.81 | 100.00 | 0.00 |
25-
# -------------------------------------------------------------------------------------------------------------------------------------
17+
# --------------------------------------------------------------------------------------------------------------
18+
# file | line % | branch % | funcs % | uncovered lines
19+
# --------------------------------------------------------------------------------------------------------------
20+
# test | | | |
21+
# fixtures | | | |
22+
# test-runner | | | |
23+
# coverage-snap | | | |
24+
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
25+
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
26+
# output | | | |
27+
# coverage-width-150.mjs | 100.00 | 100.00 | 100.00 |
28+
# --------------------------------------------------------------------------------------------------------------
29+
# all files | 60.81 | 100.00 | 0.00 |
30+
# --------------------------------------------------------------------------------------------------------------
2631
# end of coverage report

test/fixtures/test-runner/output/coverage-width-80-uncovered-lines.snapshot

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@ ok 1 - Coverage Print Fixed Width 100
1515
# duration_ms *
1616
# start of coverage report
1717
# --------------------------------------------------------------------------------------------------
18-
# file | line % | branch % | funcs % | uncovered lines
18+
# file | line % | branch % | funcs % | uncovered lines
1919
# --------------------------------------------------------------------------------------------------
20-
# …ap/a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52
21-
# …ap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
22-
# …ines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 17-19 29-30 40-42 45-47 50-52 55-57 59-6…
23-
# …nes.mjs | 100.00 | 100.00 | 100.00 |
20+
# test | | | |
21+
# fixtures | | | |
22+
# test-runner | | | |
23+
# coverage-snap | | | |
24+
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 1…
25+
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
26+
# many-uncovered-lines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 1…
27+
# output | | | |
28+
# coverage-width-80-uncovered-lines.mjs | 100.00 | 100.00 | 100.00 |
2429
# --------------------------------------------------------------------------------------------------
25-
# all fil… | 52.80 | 60.00 | 1.61 |
30+
# all files | 52.80 | 60.00 | 1.61 |
2631
# --------------------------------------------------------------------------------------------------
2732
# end of coverage report

test/fixtures/test-runner/output/coverage-width-80.snapshot

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@ ok 1 - Coverage Print Fixed Width 80
1515
# duration_ms *
1616
# start of coverage report
1717
# ------------------------------------------------------------------------------
18-
# file | line % | branch % | funcs % | …
18+
# file | line % | branch % | funcs % | uncovered li
1919
# ------------------------------------------------------------------------------
20-
# test/fixtures/test-runner/coverage-snap/a.js | 55.77 | 100.00 | 0.00 | …
21-
# test/fixtures/test-runner/coverage-snap/b.js | 45.45 | 100.00 | 0.00 | …
22-
# …es/test-runner/output/coverage-width-80.mjs | 100.00 | 100.00 | 100.00 |
20+
# test | | | |
21+
# fixtures | | | |
22+
# test-runner | | | |
23+
# coverage-snap | | | |
24+
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-…
25+
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
26+
# output | | | |
27+
# coverage-width-80.mjs | 100.00 | 100.00 | 100.00 |
2328
# ------------------------------------------------------------------------------
24-
# all files | 60.81 | 100.00 | 0.00 |
29+
# all files | 60.81 | 100.00 | 0.00 |
2530
# ------------------------------------------------------------------------------
2631
# end of coverage report

0 commit comments

Comments
 (0)