diff --git a/README.md b/README.md index 1895b4ed..49e5ba30 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,9 @@ branch. When this is set a diff of the coverage percentages is shown. ##### `filter-changed-files` (**Default: false**) If set to true, only changed files will be included in the report. Total percentage will still include all files. +##### `excluded-files` (**Default: []**) +A list of contains string for files without unit testing. Total percentage will be impacted. + ##### `delete-old-comments` (**Default: false**) If set to true, old comments will be deleted before a new comment is posted diff --git a/action.yml b/action.yml index 7f66e8cf..a21d1468 100644 --- a/action.yml +++ b/action.yml @@ -19,6 +19,10 @@ inputs: description: Set to true to only comment with coverage on files changed in this commit required: false default: false + excluded-files: + description: List of files to be excluded from coverage + required: false + default: [] delete-old-comments: description: Set to true to delete old Coverage Report comments required: false diff --git a/dist/main.js b/dist/main.js index 3f77464a..95fdf9db 100644 --- a/dist/main.js +++ b/dist/main.js @@ -22749,17 +22749,28 @@ function parse$2(data) { } // Get the total coverage percentage from the lcov data. -function percentage(lcov) { +function percentage(lcov, options) { let hit = 0; let found = 0; for (const entry of lcov) { - hit += entry.lines.hit; - found += entry.lines.found; + if (shouldBeIncluded(entry.file, options)) { + hit += entry.lines.hit; + found += entry.lines.found; + } } return (hit / found) * 100 } +function shouldBeIncluded(fileName, options) { + for (let i in options.excludedFiles) { + if (fileName.startsWith(options.excludedFiles[i])) { + return false + } + } + return true +} + function tag(name) { return function(...children) { const props = @@ -22833,10 +22844,15 @@ function filterAndNormaliseLcov(lcov, options) { ...file, file: normalisePath(file.file), })) - .filter(file => shouldBeIncluded(file.file, options)) + .filter(file => shouldBeIncluded$1(file.file, options)) } -function shouldBeIncluded(fileName, options) { +function shouldBeIncluded$1(fileName, options) { + for (let i in options.excludedFiles) { + if (fileName.startsWith(options.excludedFiles[i])) { + return false + } + } if (!options.shouldFilterChangedFiles) { return true } @@ -22966,7 +22982,7 @@ function comment(lcov, options) { options.base, )} will be` : `Coverage for this commit`, - table(tbody(tr(th(percentage(lcov).toFixed(2), "%")))), + table(tbody(tr(th(percentage(lcov, options).toFixed(2), "%")))), "\n\n", details( summary( @@ -22984,8 +23000,8 @@ function diff(lcov, before, options) { return comment(lcov, options) } - const pbefore = percentage(before); - const pafter = percentage(lcov); + const pbefore = percentage(before, options); + const pafter = percentage(lcov, options); const pdiff = pafter - pbefore; const plus = pdiff > 0 ? "+" : ""; const arrow = pdiff === 0 ? "" : pdiff < 0 ? "▾" : "▴"; @@ -23094,8 +23110,14 @@ async function main$1() { const githubClient = new github_2(token); const lcovFile = core$1.getInput("lcov-file") || "./coverage/lcov.info"; const baseFile = core$1.getInput("lcov-base"); - const shouldFilterChangedFiles = core$1.getInput("filter-changed-files").toLowerCase() === 'true'; - const shouldDeleteOldComments = core$1.getInput("delete-old-comments").toLowerCase() === 'true'; + const shouldFilterChangedFiles = + core$1.getInput("filter-changed-files").toLowerCase() === "true"; + const excludedFiles = core$1 + .getInput("excluded-files") + .split("\n") + .filter(x => x !== ""); + const shouldDeleteOldComments = + core$1.getInput("delete-old-comments").toLowerCase() === "true"; const title = core$1.getInput("title"); const raw = await fs.promises.readFile(lcovFile, "utf-8").catch(err => null); @@ -23127,6 +23149,7 @@ async function main$1() { } options.shouldFilterChangedFiles = shouldFilterChangedFiles; + options.excludedFiles = excludedFiles; options.title = title; if (shouldFilterChangedFiles) { diff --git a/src/comment.js b/src/comment.js index 73cf3dd5..e1508c95 100644 --- a/src/comment.js +++ b/src/comment.js @@ -11,7 +11,7 @@ export function comment(lcov, options) { options.base, )} will be` : `Coverage for this commit`, - table(tbody(tr(th(percentage(lcov).toFixed(2), "%")))), + table(tbody(tr(th(percentage(lcov, options).toFixed(2), "%")))), "\n\n", details( summary( @@ -29,8 +29,8 @@ export function diff(lcov, before, options) { return comment(lcov, options) } - const pbefore = percentage(before) - const pafter = percentage(lcov) + const pbefore = percentage(before, options) + const pafter = percentage(lcov, options) const pdiff = pafter - pbefore const plus = pdiff > 0 ? "+" : "" const arrow = pdiff === 0 ? "" : pdiff < 0 ? "▾" : "▴" diff --git a/src/index.js b/src/index.js index a2ace080..6e1d0da7 100644 --- a/src/index.js +++ b/src/index.js @@ -17,6 +17,10 @@ async function main() { const baseFile = core.getInput("lcov-base") const shouldFilterChangedFiles = core.getInput("filter-changed-files").toLowerCase() === "true" + const excludedFiles = core + .getInput("excluded-files") + .split("\n") + .filter(x => x !== "") const shouldDeleteOldComments = core.getInput("delete-old-comments").toLowerCase() === "true" const title = core.getInput("title") @@ -50,6 +54,7 @@ async function main() { } options.shouldFilterChangedFiles = shouldFilterChangedFiles + options.excludedFiles = excludedFiles options.title = title if (shouldFilterChangedFiles) { diff --git a/src/lcov.js b/src/lcov.js index f403c0b3..46fdc946 100644 --- a/src/lcov.js +++ b/src/lcov.js @@ -14,13 +14,24 @@ export function parse(data) { } // Get the total coverage percentage from the lcov data. -export function percentage(lcov) { +export function percentage(lcov, options) { let hit = 0 let found = 0 for (const entry of lcov) { - hit += entry.lines.hit - found += entry.lines.found + if (shouldBeIncluded(entry.file, options)) { + hit += entry.lines.hit + found += entry.lines.found + } } return (hit / found) * 100 } + +function shouldBeIncluded(fileName, options) { + for (let i in options.excludedFiles) { + if (fileName.startsWith(options.excludedFiles[i])) { + return false + } + } + return true +} diff --git a/src/lcov_test.js b/src/lcov_test.js index ff61f3f4..a0171fe4 100644 --- a/src/lcov_test.js +++ b/src/lcov_test.js @@ -110,10 +110,17 @@ test("parse should fail on invalid lcov", async function() { }) test("percentage should calculate the correct percentage", function() { + const options = { + excludedFiles: ["lib/ignore"], + } expect( - percentage([ - { lines: { hit: 20, found: 25 } }, - { lines: { hit: 10, found: 15 } }, - ]), + percentage( + [ + { lines: { hit: 20, found: 25 }, file: "" }, + { lines: { hit: 10, found: 15 }, file: "" }, + { lines: { hit: 0, found: 15 }, file: "lib/ignore" }, + ], + options, + ), ).toBe(75) }) diff --git a/src/tabulate.js b/src/tabulate.js index f382fa20..d0633bcc 100644 --- a/src/tabulate.js +++ b/src/tabulate.js @@ -44,6 +44,11 @@ function filterAndNormaliseLcov(lcov, options) { } function shouldBeIncluded(fileName, options) { + for (let i in options.excludedFiles) { + if (fileName.startsWith(options.excludedFiles[i])) { + return false + } + } if (!options.shouldFilterChangedFiles) { return true } diff --git a/src/tabulate_test.js b/src/tabulate_test.js index 78038182..ff52f175 100644 --- a/src/tabulate_test.js +++ b/src/tabulate_test.js @@ -367,6 +367,181 @@ test("filtered tabulate should generate a correct table with only changed files" expect(tabulate(data, options)).toBe(html) }) +test("filtered tabulate should generate a correct table with excluded files", function() { + const data = [ + { + file: "/files/project/index.js", + functions: { + found: 0, + hit: 0, + details: [], + }, + }, + { + file: "/files/project/src/foo.js", + lines: { + found: 23, + hit: 21, + details: [ + { + line: 20, + hit: 3, + }, + { + line: 21, + hit: 3, + }, + { + line: 22, + hit: 3, + }, + ], + }, + functions: { + hit: 2, + found: 3, + details: [ + { + name: "foo", + line: 19, + }, + { + name: "bar", + line: 33, + }, + { + name: "baz", + line: 54, + }, + ], + }, + branches: { + hit: 3, + found: 3, + details: [ + { + line: 21, + block: 0, + branch: 0, + taken: 1, + }, + { + line: 21, + block: 0, + branch: 1, + taken: 2, + }, + { + line: 37, + block: 1, + branch: 0, + taken: 0, + }, + ], + }, + }, + { + file: "/files/project/src/bar/baz.js", + lines: { + found: 10, + hit: 5, + details: [ + { + line: 20, + hit: 0, + }, + { + line: 21, + hit: 0, + }, + { + line: 27, + hit: 0, + }, + ], + }, + functions: { + hit: 2, + found: 3, + details: [ + { + name: "foo", + line: 19, + }, + { + name: "bar", + line: 33, + }, + { + name: "baz", + line: 54, + }, + ], + }, + }, + ] + + const options = { + repository: "example/foo", + commit: "2e15bee6fe0df5003389aa5ec894ec0fea2d874a", + prefix: "/files/project/", + excludedFiles: ["/files/project/src/bar"], + } + + const html = table( + tbody( + tr( + th("File"), + th("Stmts"), + th("Branches"), + th("Funcs"), + th("Lines"), + th("Uncovered Lines"), + ), + tr( + td( + a( + { + href: `https://github.com/${options.repository}/blob/${options.commit}/index.js`, + }, + "index.js", + ), + ), + td("100%"), + td("N/A"), + td("100%"), + td("N/A"), + td(), + ), + tr(td({ colspan: 6 }, b("src"))), + tr( + td( + "   ", + a( + { + href: `https://github.com/${options.repository}/blob/${options.commit}/src/foo.js`, + }, + "foo.js", + ), + ), + td(b("89.66%")), + td("100%"), + td(b("66.67%")), + td(b("91.30%")), + td( + a( + { + href: `https://github.com/${options.repository}/blob/${options.commit}/src/foo.js#L37`, + }, + 37, + ), + ), + ), + ), + ) + expect(tabulate(data, options)).toBe(html) +}) + test("filtered tabulate should fix backwards slashes in filenames", function() { const data = [ {