Skip to content

Commit

Permalink
test_runner: code coverage files tree view
Browse files Browse the repository at this point in the history
  • Loading branch information
pmarchini committed Aug 30, 2024
1 parent 348a858 commit 694ee5e
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 122 deletions.
134 changes: 68 additions & 66 deletions lib/internal/test_runner/utils.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict';
const {
ArrayPrototypeFlatMap,
ArrayPrototypeForEach,
ArrayPrototypeJoin,
ArrayPrototypeMap,
ArrayPrototypePush,
ArrayPrototypeReduce,
ArrayPrototypeSome,
MathFloor,
MathMax,
MathMin,
NumberParseInt,
Expand Down Expand Up @@ -406,6 +406,32 @@ const kColumns = ['line %', 'branch %', 'funcs %'];
const kColumnsKeys = ['coveredLinePercent', 'coveredBranchPercent', 'coveredFunctionPercent'];
const kSeparator = ' | ';

function buildFileTree(summary) {
const tree = { __proto__: null };
let treeDepth = 0;
let longestFile = 0;

ArrayPrototypeForEach(summary.files, (file) => {
const parts = relative(summary.workingDirectory, file.path).split('/');
let current = tree;
ArrayPrototypeForEach(parts, (part, index) => {
if (!current[part]) {
current[part] = { __proto__: null };
}
current = current[part];
// If this is the last part, add the file to the tree
if (index === parts.length - 1) {
current.file = file;
current.finalPath = parts;
}
});
treeDepth = MathMax(treeDepth, parts.length);
longestFile = MathMax(longestFile, ...parts.map((part) => part.length));
});

return { __proto__: null, tree, treeDepth, longestFile };
}

function getCoverageReport(pad, summary, symbol, color, table) {
const prefix = `${pad}${symbol}`;
let report = `${color}${prefix}start of coverage report\n`;
Expand All @@ -415,10 +441,15 @@ function getCoverageReport(pad, summary, symbol, color, table) {
let uncoveredLinesPadLength;
let tableWidth;

// Create a tree of file paths
const { tree, treeDepth, longestFile } = buildFileTree(summary);

if (table) {
// Get expected column sizes
filePadLength = table && ArrayPrototypeReduce(summary.files, (acc, file) =>
MathMax(acc, relative(summary.workingDirectory, file.path).length), 0);
// Calculate expected column sizes based on the tree
// Every level of the tree adds 2 to the column size + the longest file name
filePadLength = table && longestFile;
filePadLength += 2 * treeDepth;
// Get the maximum length of the file path or 'file'
filePadLength = MathMax(filePadLength, 'file'.length);
const fileWidth = filePadLength + 2;

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

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

function getfilePathMultiline(string, width, pad, coverage) {
if (!table) return string;

const lines = [];
let currentLine = '';

for (const word of StringPrototypeSplit(string, '\\')) {
if (currentLine.length + word.length + 1 <= width) {
// If adding the next word fits in the current line, append it
currentLine += (currentLine.length > 0 ? '\\' : '') + word;
} else {
// If adding the next word exceeds the width, start a new line
ArrayPrototypePush(lines, currentLine);
currentLine = word;
}
}

// Add the last line if any
if (currentLine.length > 0) {
ArrayPrototypePush(lines, currentLine);
}

const truncatedLines = ArrayPrototypeMap(lines, (line) => StringPrototypeSlice(line, 0, width));

// Delete empty lines if any
for (let i = 0; i < truncatedLines.length; ++i) {
if (truncatedLines[i].length === 0) {
truncatedLines.splice(i, 1);
}
}

return getCell(
ArrayPrototypeJoin(truncatedLines, '\n'),
width,
pad,
false,
coverage,
);
}

// Head
if (table) report += addTableLine(prefix, tableWidth);
report += `${prefix}${getCell('file', filePadLength, StringPrototypePadEnd, truncateEnd)}${kSeparator}` +
`${ArrayPrototypeJoin(ArrayPrototypeMap(kColumns, (column, i) => getCell(column, columnPadLengths[i], StringPrototypePadStart)), kSeparator)}${kSeparator}` +
`${getCell('uncovered lines', uncoveredLinesPadLength, false, truncateEnd)}\n`;
`${ArrayPrototypeJoin(ArrayPrototypeMap(kColumns, (column, i) => getCell(column, columnPadLengths[i], StringPrototypePadStart)), kSeparator)}${kSeparator}` +
`${getCell('uncovered lines', uncoveredLinesPadLength, false, truncateEnd)}\n`;
if (table) report += addTableLine(prefix, tableWidth);

// Body
for (let i = 0; i < summary.files.length; ++i) {
const file = summary.files[i];
const relativePath = relative(summary.workingDirectory, file.path);

let fileCoverage = 0;
const coverages = ArrayPrototypeMap(kColumnsKeys, (columnKey) => {
const percent = file[columnKey];
fileCoverage += percent;
return percent;
});
fileCoverage /= kColumnsKeys.length;
// Body using the tree
function printTree(tree, depth) {
for (const key in tree) {
if (tree[key].file) {
const file = tree[key].file;
const fileName = file.path.split('/').pop();

let fileCoverage = 0;
const coverages = ArrayPrototypeMap(kColumnsKeys, (columnKey) => {
const percent = file[columnKey];
fileCoverage += percent;
return percent;
});
fileCoverage /= kColumnsKeys.length;

report += `${prefix}${StringPrototypeRepeat(' ', depth)}${getCell(fileName, filePadLength - depth, StringPrototypePadEnd, false, fileCoverage)}${kSeparator}` +
`${ArrayPrototypeJoin(ArrayPrototypeMap(coverages, (coverage, j) => getCell(NumberPrototypeToFixed(coverage, 2), columnPadLengths[j], StringPrototypePadStart, false, coverage)), kSeparator)}${kSeparator}` +
`${getCell(formatUncoveredLines(getUncoveredLines(file.lines), table), uncoveredLinesPadLength, false, truncateEnd)}\n`;
} else {
// Print a line for the directory with empty columns
report += `${prefix}${StringPrototypeRepeat(' ', depth)}${getCell(key, filePadLength - depth, StringPrototypePadEnd, false)}${kSeparator}` +
`${ArrayPrototypeJoin(ArrayPrototypeMap(columnPadLengths, (columnPadLength) => getCell('', columnPadLength, StringPrototypePadStart, false)), kSeparator)}${kSeparator}` +
`${getCell('', uncoveredLinesPadLength, false, truncateEnd)}\n`;

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


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

report += `${prefix}end of coverage report\n`;
Expand All @@ -542,7 +545,6 @@ function getCoverageReport(pad, summary, symbol, color, table) {
}
return report;
}

module.exports = {
convertStringToRegExp,
countCompletedTest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ ok 1 - Coverage Print Fixed Width 100
# duration_ms *
# start of coverage report
# --------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# file | line % | branch % | funcs % | uncovered lines
# --------------------------------------------------------------------------------------------------
# …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
# …ap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# …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…
# …nes.mjs | 100.00 | 100.00 | 100.00 |
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 …
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# many-uncovered-lines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 …
# output | | | |
# coverage-width-100-uncovered-lines.mjs | 100.00 | 100.00 | 100.00 |
# --------------------------------------------------------------------------------------------------
# all fil… | 52.80 | 60.00 | 1.61 |
# all files | 52.80 | 60.00 | 1.61 |
# --------------------------------------------------------------------------------------------------
# end of coverage report
15 changes: 10 additions & 5 deletions test/fixtures/test-runner/output/coverage-width-100.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ ok 1 - Coverage Print Fixed Width 100
# duration_ms *
# start of coverage report
# --------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# file | line % | branch % | funcs % | uncovered lines
# --------------------------------------------------------------------------------------------------
# test/fixtures/test-runner/coverage-snap/a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 …
# test/fixtures/test-runner/coverage-snap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# …tures/test-runner/output/coverage-width-100.mjs | 100.00 | 100.00 | 100.00 |
# 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-4…
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# output | | | |
# coverage-width-100.mjs | 100.00 | 100.00 | 100.00 |
# --------------------------------------------------------------------------------------------------
# all files | 60.81 | 100.00 | 0.00 |
# all files | 60.81 | 100.00 | 0.00 |
# --------------------------------------------------------------------------------------------------
# end of coverage report
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ ok 1 - Coverage Print Fixed Width 150
# duration_ms *
# start of coverage report
# ----------------------------------------------------------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# file | line % | branch % | funcs % | uncovered lines
# ----------------------------------------------------------------------------------------------------------------------------------------------------
# …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
# …ap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# …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 …
# …nes.mjs | 100.00 | 100.00 | 100.00 |
# 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
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# 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…
# output | | | |
# coverage-width-150-uncovered-lines.mjs | 100.00 | 100.00 | 100.00 |
# ----------------------------------------------------------------------------------------------------------------------------------------------------
# all fil… | 52.80 | 60.00 | 1.61 |
# all files | 52.80 | 60.00 | 1.61 |
# ----------------------------------------------------------------------------------------------------------------------------------------------------
# end of coverage report
23 changes: 14 additions & 9 deletions test/fixtures/test-runner/output/coverage-width-150.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@ ok 1 - Coverage Print Fixed Width 150
# todo 0
# duration_ms *
# start of coverage report
# -------------------------------------------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# -------------------------------------------------------------------------------------------------------------------------------------
# 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
# test/fixtures/test-runner/coverage-snap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# test/fixtures/test-runner/output/coverage-width-150.mjs | 100.00 | 100.00 | 100.00 |
# -------------------------------------------------------------------------------------------------------------------------------------
# all files | 60.81 | 100.00 | 0.00 |
# -------------------------------------------------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# --------------------------------------------------------------------------------------------------------------
# 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
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# output | | | |
# coverage-width-150.mjs | 100.00 | 100.00 | 100.00 |
# --------------------------------------------------------------------------------------------------------------
# all files | 60.81 | 100.00 | 0.00 |
# --------------------------------------------------------------------------------------------------------------
# end of coverage report
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ ok 1 - Coverage Print Fixed Width 100
# duration_ms *
# start of coverage report
# --------------------------------------------------------------------------------------------------
# file | line % | branch % | funcs % | uncovered lines
# file | line % | branch % | funcs % | uncovered lines
# --------------------------------------------------------------------------------------------------
# …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
# …ap/b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# …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…
# …nes.mjs | 100.00 | 100.00 | 100.00 |
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-15 1…
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# many-uncovered-lines.js | 50.99 | 42.86 | 1.92 | 5-7 9-11 13-15 1…
# output | | | |
# coverage-width-80-uncovered-lines.mjs | 100.00 | 100.00 | 100.00 |
# --------------------------------------------------------------------------------------------------
# all fil… | 52.80 | 60.00 | 1.61 |
# all files | 52.80 | 60.00 | 1.61 |
# --------------------------------------------------------------------------------------------------
# end of coverage report
15 changes: 10 additions & 5 deletions test/fixtures/test-runner/output/coverage-width-80.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ ok 1 - Coverage Print Fixed Width 80
# duration_ms *
# start of coverage report
# ------------------------------------------------------------------------------
# file | line % | branch % | funcs % | …
# file | line % | branch % | funcs % | uncovered li
# ------------------------------------------------------------------------------
# test/fixtures/test-runner/coverage-snap/a.js | 55.77 | 100.00 | 0.00 | …
# test/fixtures/test-runner/coverage-snap/b.js | 45.45 | 100.00 | 0.00 | …
# …es/test-runner/output/coverage-width-80.mjs | 100.00 | 100.00 | 100.00 |
# test | | | |
# fixtures | | | |
# test-runner | | | |
# coverage-snap | | | |
# a.js | 55.77 | 100.00 | 0.00 | 5-7 9-11 13-…
# b.js | 45.45 | 100.00 | 0.00 | 5-7 9-11
# output | | | |
# coverage-width-80.mjs | 100.00 | 100.00 | 100.00 |
# ------------------------------------------------------------------------------
# all files | 60.81 | 100.00 | 0.00 |
# all files | 60.81 | 100.00 | 0.00 |
# ------------------------------------------------------------------------------
# end of coverage report
Loading

0 comments on commit 694ee5e

Please sign in to comment.