From 2a741d6ebaa68f3ec32c0c6586169227ffe648d7 Mon Sep 17 00:00:00 2001 From: David Losert Date: Sat, 2 Nov 2024 14:26:33 +0100 Subject: [PATCH] feat: Enhance file coverage reporting with comparison metrics --- src/index.ts | 2 +- src/inputs/options.ts | 1 - src/report/generateFileCoverageHtml.test.ts | 68 +++++++++++++++++++++ src/report/generateFileCoverageHtml.ts | 17 ++++-- src/report/generateSummaryTableHtml.ts | 14 +---- src/report/getCompareString.ts | 16 +++++ 6 files changed, 97 insertions(+), 21 deletions(-) create mode 100644 src/report/getCompareString.ts diff --git a/src/index.ts b/src/index.ts index dada21a..26aedf6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,7 +16,6 @@ import { generateSummaryTableHtml } from "./report/generateSummaryTableHtml.js"; import type { JsonSummary } from "./types/JsonSummary.js"; import { writeSummaryToCommit } from "./writeSummaryToComment.js"; import { writeSummaryToPR } from "./writeSummaryToPR.js"; -import { aw } from "vitest/dist/chunks/reporters.C_zwCd4j.js"; type GitHubSummary = typeof core.summary; @@ -61,6 +60,7 @@ const run = async () => { const jsonFinal = await parseVitestJsonFinal(options.jsonFinalPath); const fileTable = generateFileCoverageHtml({ jsonSummary, + jsonSummaryCompare, jsonFinal, fileCoverageMode: options.fileCoverageMode, pullChanges, diff --git a/src/inputs/options.ts b/src/inputs/options.ts index 125b96d..12948f2 100644 --- a/src/inputs/options.ts +++ b/src/inputs/options.ts @@ -8,7 +8,6 @@ import { getPullRequestNumber } from "./getPullRequestNumber"; import { getViteConfigPath } from "./getViteConfigPath"; import { parseCoverageThresholds } from "./parseCoverageThresholds"; import { getCommentOn, type CommentOn } from "./getCommentOn"; -import { report } from "node:process"; type Options = { fileCoverageMode: FileCoverageMode; diff --git a/src/report/generateFileCoverageHtml.test.ts b/src/report/generateFileCoverageHtml.test.ts index 4e363db..fce7ef4 100644 --- a/src/report/generateFileCoverageHtml.test.ts +++ b/src/report/generateFileCoverageHtml.test.ts @@ -244,4 +244,72 @@ describe("generateFileCoverageHtml()", () => { .length; expect(equalSignCount).toBe(4); }); + + it("renders a plus sign and the increased percentage for files with increased coverage", () => { + const jsonSummary: JsonSummary = createMockJsonSummary({ + "file1.ts": createMockCoverageReport({ + branches: createMockReportNumbers({ pct: 70 }), + }), + }); + + const jsonSummaryCompare: JsonSummary = createMockJsonSummary({ + "file1.ts": createMockCoverageReport({ + branches: createMockReportNumbers({ pct: 60 }), + }), + }); + const jsonFinal: JsonFinal = { + ...createJsonFinalEntry("src/exampleFile.ts", [ + { line: 1, covered: true }, + ]), + }; + + const html = generateFileCoverageHtml({ + jsonSummary, + jsonSummaryCompare, + jsonFinal, + fileCoverageMode: FileCoverageMode.All, + pullChanges: [], + commitSHA: "test-sha", + }); + + expect(html).toContain("file1.ts"); + expect(html).toContain(`${icons.increase} +10.00%`); + const equalSignCount = (html.match(new RegExp(icons.increase, "g")) || []) + .length; + expect(equalSignCount).toBe(1); + }); + + it("renders a minus sign and the decreased percentage for files with decreased coverage", () => { + const jsonSummary: JsonSummary = createMockJsonSummary({ + "file1.ts": createMockCoverageReport({ + branches: createMockReportNumbers({ pct: 70 }), + }), + }); + + const jsonSummaryCompare: JsonSummary = createMockJsonSummary({ + "file1.ts": createMockCoverageReport({ + branches: createMockReportNumbers({ pct: 80 }), + }), + }); + const jsonFinal: JsonFinal = { + ...createJsonFinalEntry("src/exampleFile.ts", [ + { line: 1, covered: true }, + ]), + }; + + const html = generateFileCoverageHtml({ + jsonSummary, + jsonSummaryCompare, + jsonFinal, + fileCoverageMode: FileCoverageMode.All, + pullChanges: [], + commitSHA: "test-sha", + }); + + expect(html).toContain("file1.ts"); + expect(html).toContain(`${icons.decrease} -10.00%`); + const equalSignCount = (html.match(new RegExp(icons.decrease, "g")) || []) + .length; + expect(equalSignCount).toBe(1); + }); }); diff --git a/src/report/generateFileCoverageHtml.ts b/src/report/generateFileCoverageHtml.ts index c0551e3..a45e5a8 100644 --- a/src/report/generateFileCoverageHtml.ts +++ b/src/report/generateFileCoverageHtml.ts @@ -9,6 +9,7 @@ import { getUncoveredLinesFromStatements, } from "./getUncoveredLinesFromStatements"; import { icons } from "../icons"; +import { getCompareString } from "./getCompareString"; type FileCoverageInputs = { jsonSummary: JsonSummary; @@ -47,10 +48,10 @@ const generateFileCoverageHtml = ({ return ` ${relativeFilePath} - ${generateCoverageCell(coverageSummary, coverageSummaryCompare, "statements")} - ${generateCoverageCell(coverageSummary, coverageSummaryCompare, "branches")} - ${generateCoverageCell(coverageSummary, coverageSummaryCompare, "functions")} - ${generateCoverageCell(coverageSummary, coverageSummaryCompare, "lines")} + ${generateCoverageCell(coverageSummary, coverageSummaryCompare, "statements")} + ${generateCoverageCell(coverageSummary, coverageSummaryCompare, "branches")} + ${generateCoverageCell(coverageSummary, coverageSummaryCompare, "functions")} + ${generateCoverageCell(coverageSummary, coverageSummaryCompare, "lines")} ${createRangeURLs(uncoveredLines, url)} `; }; @@ -107,8 +108,12 @@ function generateCoverageCell( summaryCompare: CoverageReport | undefined, field: keyof CoverageReport, ): string { - const icon = summaryCompare ? icons.equal : ""; - return `${summary[field].pct}%
${icon}`; + let diffText = ""; + if (summaryCompare) { + const diff = summary[field].pct - summaryCompare[field].pct; + diffText = `
${getCompareString(diff)}`; + } + return `${summary[field].pct}%${diffText}`; } function formatGroupLine(caption: string): string { diff --git a/src/report/generateSummaryTableHtml.ts b/src/report/generateSummaryTableHtml.ts index 03c8761..fe80f56 100644 --- a/src/report/generateSummaryTableHtml.ts +++ b/src/report/generateSummaryTableHtml.ts @@ -2,6 +2,7 @@ import { oneLine } from "common-tags"; import { icons } from "../icons"; import type { CoverageReport, ReportNumbers } from "../types/JsonSummary"; import type { Thresholds } from "../types/Threshold"; +import { getCompareString } from "./getCompareString"; function generateSummaryTableHtml( jsonReport: CoverageReport, @@ -69,17 +70,4 @@ function generateTableRow({ `; } -function getCompareString(percentDiff: number): string { - if (percentDiff === 0) { - return `${icons.equal} ±0%`; - } - - if (percentDiff > 0) { - return `${icons.increase} +${percentDiff.toFixed(2)}%`; - } - - // The - char is already included in a negative number - return `${icons.decrease} ${percentDiff.toFixed(2)}%`; -} - export { generateSummaryTableHtml }; diff --git a/src/report/getCompareString.ts b/src/report/getCompareString.ts new file mode 100644 index 0000000..5a45f6b --- /dev/null +++ b/src/report/getCompareString.ts @@ -0,0 +1,16 @@ +import { icons } from "../icons"; + +function getCompareString(percentDiff: number): string { + if (percentDiff === 0) { + return `${icons.equal} ±0%`; + } + + if (percentDiff > 0) { + return `${icons.increase} +${percentDiff.toFixed(2)}%`; + } + + // The - char is already included in a negative number + return `${icons.decrease} ${percentDiff.toFixed(2)}%`; +} + +export { getCompareString };