From a2c862951f6ed8a6b33664156ab42ebf5ba1f259 Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Mon, 27 Jun 2022 17:08:37 -0500 Subject: [PATCH 01/10] add `newFileCoverageThreshold` to config and `isNewFile` to results --- src/common.ts | 4 + src/coverageDiffer.ts | 7 +- src/diffChecker.test.ts | 156 +++++++++++++++++++++++++++++++++++- src/diffChecker.ts | 65 +++++++++------ src/resultFormatter.test.ts | 37 +++++++++ src/resultFormatter.ts | 8 +- src/summaries.fixture.ts | 85 +++++++++++++++++++- 7 files changed, 326 insertions(+), 36 deletions(-) diff --git a/src/common.ts b/src/common.ts index 46d6ea2..a48524e 100644 --- a/src/common.ts +++ b/src/common.ts @@ -4,6 +4,7 @@ export interface CoverageSummary { statements: CoverageInfo; functions: CoverageInfo; branches: CoverageInfo; + isNewFile: boolean; } export interface CoverageInfo { @@ -32,6 +33,8 @@ export interface ConfigOptions { coverageThreshold?: number; /* Fail coverage check if per-file coverage decrease is lower */ coverageDecreaseThreshold?: number; + /* Fail coverage check if per-file coverage is lower than this for new files only */ + newFileCoverageThreshold?: number; } export interface DiffCheckResults { @@ -51,6 +54,7 @@ export interface FileResultFormat { pcts: FileResultFields; decreased: boolean; belowThreshold: boolean; + isNewFile: boolean; } export interface FileResultFields { diff --git a/src/coverageDiffer.ts b/src/coverageDiffer.ts index 1d6072e..8a62c17 100644 --- a/src/coverageDiffer.ts +++ b/src/coverageDiffer.ts @@ -11,7 +11,7 @@ export const coverageDiffer = ( ): JsonSummary => { const baseMap = objectToMap(base); const headMap = objectToMap(head); - const diffMap = new Map(); + const diffMap = new Map(); // Compare head against base for changed/added files. headMap.forEach((v, k) => { @@ -22,7 +22,7 @@ export const coverageDiffer = ( diffMap.set(k, diffSummary(v, fileSummary)); } else { // New file. - diffMap.set(k, v); + diffMap.set(k, {...v, isNewFile: true}); } }); @@ -40,7 +40,8 @@ const diffSummary = ( lines: diffInfo(summaryA.lines, summaryB.lines), statements: diffInfo(summaryA.statements, summaryB.statements), functions: diffInfo(summaryA.functions, summaryB.functions), - branches: diffInfo(summaryA.branches, summaryB.branches) + branches: diffInfo(summaryA.branches, summaryB.branches), + isNewFile: false }; }; diff --git a/src/diffChecker.test.ts b/src/diffChecker.test.ts index be735bd..a695b6a 100644 --- a/src/diffChecker.test.ts +++ b/src/diffChecker.test.ts @@ -4,7 +4,9 @@ import { onlyLinesIncreased, fileNotCovered, fileHalfCovered, - fileFullCoveredfileHalfCovered + fileFullCoveredfileHalfCovered, + newFileNotCovered, + newFileHalfCovered } from './summaries.fixture'; import { DiffCheckResults } from './common'; import { expectToMatchObject } from './testHelpers'; @@ -134,12 +136,49 @@ describe('diffChecker', () => { }); it('should not regress', () => { - // Total is now 50% but overall threshold is 40% so it still passes. + // Total is now 50% but the first file didn't change so no regression expect(result.regression).toBe(false); }); it('should be below threshold', () => { - // Total is now 50% but overall threshold is 40% so it still passes. + // Total is now 50% but file threshold is 60% so it should be belowThreshold. + expect(result.belowThreshold).toBe(true); + }); + + it('outputs correct total percentages', () => { + expectToMatchObject(result.totals, { + belowThreshold: true, + decreased: false, // Threshold is 60 + pcts: { + branches: 50, + functions: 50, + lines: 50, + statements: 50 + } + }); + }); + }); + + describe('new file with no coverage below threshold', () => { + beforeEach(() => { + // Set coverageDecreaseThreshold to 100% so we only test coverageThreshold. + result = diffChecker( + fileFullCovered, + newFileNotCovered, + undefined, + 60, + 100, + 60 + ); + }); + + it('should not regress', () => { + // Total is now 50% but the first file didn't change so no regression + expect(result.regression).toBe(false); + }); + + it('should be below threshold', () => { + // Total is now 50% but file threshold is 60% so it should be belowThreshold. expect(result.belowThreshold).toBe(true); }); @@ -157,6 +196,117 @@ describe('diffChecker', () => { }); }); + describe('new file with no coverage above threshold', () => { + beforeEach(() => { + // Set coverageDecreaseThreshold to 100% so we only test coverageThreshold. + result = diffChecker( + fileFullCovered, + newFileNotCovered, + undefined, + 40, + 100, + 40 + ); + }); + + it('should not regress', () => { + // Total is now 50% but the first file didn't change so no regression + expect(result.regression).toBe(false); + }); + + it('should be below threshold', () => { + // Total is now 50% but file threshold is 40%, and new file threshold is 40, so it should be below the threshold + expect(result.belowThreshold).toBe(true); + }); + + it('outputs correct total percentages', () => { + expectToMatchObject(result.totals, { + belowThreshold: false, + decreased: false, // Threshold is 40 + pcts: { + branches: 50, + functions: 50, + lines: 50, + statements: 50 + } + }); + }); + }); + + describe('new file with half coverage below threshold', () => { + beforeEach(() => { + // Set coverageDecreaseThreshold to 100% so we only test coverageThreshold. + result = diffChecker( + fileFullCovered, + newFileHalfCovered, + undefined, + 40, + 100, + 60 + ); + }); + + it('should not regress', () => { + // Total is now 75% and the first file didn't change so no regression + expect(result.regression).toBe(false); + }); + + it.only('should be below threshold', () => { + // Total is now 75% but file threshold is 60% so it should be belowThreshold + expect(result.belowThreshold).toBe(true); + }); + + it('outputs correct total percentages', () => { + expectToMatchObject(result.totals, { + belowThreshold: false, // Threshold is 60, total is 75, total is not below, but file is + decreased: false, + pcts: { + branches: 75, + functions: 75, + lines: 75, + statements: 75 + } + }); + }); + }); + + describe('new file with half coverage above threshold', () => { + beforeEach(() => { + // Set coverageDecreaseThreshold to 100% so we only test coverageThreshold. + result = diffChecker( + fileFullCovered, + newFileNotCovered, + undefined, + 40, + 100, + 45 + ); + }); + + it('should not regress', () => { + // Total is now 50% but the first file didn't change so no regression + expect(result.regression).toBe(false); + }); + + it('should not be below threshold', () => { + // Total is now 50% but file threshold is 40%, and new file threshold is 45, so it should be above the threshold + expect(result.belowThreshold).toBe(false); + }); + + it('outputs correct total percentages', () => { + expectToMatchObject(result.totals, { + belowThreshold: false, // Threshold is 40, total is 50 + decreased: false, + pcts: { + branches: 50, + functions: 50, + lines: 50, + statements: 50 + } + }); + }); + }); + describe('skip non changed files', () => { it('should skip non changed files', () => { result = diffChecker(fileFullCovered, fileFullCovered); diff --git a/src/diffChecker.ts b/src/diffChecker.ts index c6f9140..e39431d 100644 --- a/src/diffChecker.ts +++ b/src/diffChecker.ts @@ -19,7 +19,8 @@ export const diffChecker = ( head: JsonSummary, checkCriteria = defaultOptions.checkCriteria!, coverageThreshold = defaultOptions.coverageThreshold!, - coverageDecreaseThreshold = defaultOptions.coverageDecreaseThreshold! + coverageDecreaseThreshold = defaultOptions.coverageDecreaseThreshold!, + newFileCoverageThreshold = coverageThreshold ): DiffCheckResults => { let regression = false; let belowThreshold = false; @@ -29,44 +30,57 @@ export const diffChecker = ( const nonZeroTest = (x: number) => x !== 0; const coverageDecreased = (x: number) => x < 0 ? Math.abs(x) >= coverageDecreaseThreshold : false; - const isBelowThreshold = (x: number) => x < coverageThreshold; + const isBelowThreshold = (x: number) => x < coverageThreshold; + const isBelowNewFileThreshold = (x: number) => x < newFileCoverageThreshold; diffMap.forEach((v, k) => { const diffPercentages = getSummaryPercentages(v); - // Only check files that changed coverage. - if (Object.values(diffPercentages).some(nonZeroTest)) { - const decreased = checkCoverageForCondition( + let itemBelowThreshold = false; + let decreased = false; + + // Only check files that changed coverage. or new files + if (v.isNewFile) { + itemBelowThreshold = checkCoverageForCondition( + head[k], + checkCriteria, + isBelowNewFileThreshold + ); + } else if (Object.values(diffPercentages).some(nonZeroTest)) { + decreased = checkCoverageForCondition( v, checkCriteria, coverageDecreased ); - const itemBelowThreshold = checkCoverageForCondition( + itemBelowThreshold = checkCoverageForCondition( head[k], checkCriteria, isBelowThreshold ); + } else { + return; + } - // Ignore the total field as we check only files. - if (k !== 'total') { - // Coverage decreased on a file or under threshold, regress. - if (decreased) { - regression = true; - } - if (itemBelowThreshold) { - belowThreshold = true; - } + // Ignore the total field as we check only files. + if (k !== 'total') { + // Coverage decreased on a file or under threshold, regress. + if (decreased) { + regression = true; + } + if (itemBelowThreshold) { + belowThreshold = true; } - - percentageMap.set(k, { - deltas: { - ...diffPercentages - }, - pcts: getSummaryPercentages(head[k]), - decreased, - belowThreshold: itemBelowThreshold - }); } + + percentageMap.set(k, { + deltas: { + ...diffPercentages + }, + pcts: getSummaryPercentages(head[k]), + decreased, + belowThreshold: itemBelowThreshold, + isNewFile: v.isNewFile + }); }); let totals = percentageMap.get('total'); @@ -85,7 +99,8 @@ export const diffChecker = ( head.total, checkCriteria, isBelowThreshold - ) + ), + isNewFile: false }; } diff --git a/src/resultFormatter.test.ts b/src/resultFormatter.test.ts index bfb2a0e..8473441 100644 --- a/src/resultFormatter.test.ts +++ b/src/resultFormatter.test.ts @@ -3,6 +3,7 @@ import { resultFormatter } from './resultFormatter'; const filesResults: FilesResults = { file1: { + isNewFile: false, deltas: { lines: 10, statements: -10, @@ -19,6 +20,41 @@ const filesResults: FilesResults = { belowThreshold: false }, file2: { + isNewFile: false, + deltas: { + lines: 10, + statements: 10, + functions: 20, + branches: 30 + }, + pcts: { + lines: 20, + statements: 5, + functions: 2, + branches: 8 + }, + decreased: false, + belowThreshold: false + }, + file3: { + isNewFile: false, + deltas: { + lines: 10, + statements: 10, + functions: 20, + branches: 30 + }, + pcts: { + lines: 20, + statements: 5, + functions: 2, + branches: 8 + }, + decreased: false, + belowThreshold: true + }, + file4: { + isNewFile: true, deltas: { lines: 10, statements: 10, @@ -37,6 +73,7 @@ const filesResults: FilesResults = { }; const totalResults: FileResultFormat = { + isNewFile: false, deltas: { lines: 100, functions: 100, diff --git a/src/resultFormatter.ts b/src/resultFormatter.ts index 8f34b22..d68da8d 100644 --- a/src/resultFormatter.ts +++ b/src/resultFormatter.ts @@ -33,14 +33,14 @@ const formatTotal = (total: FileResultFormat): string => { const formatFilesResults = (files: FilesResults): string => { let noChange = true; const table: Array<(string | number)[]> = []; - const header = ['Ok', 'File', 'Lines', 'Branches', 'Functions', 'Statements']; + const header = ['Ok', 'File (✨=New File)', 'Lines', 'Branches', 'Functions', 'Statements']; table.push(header); Object.keys(files).forEach((file) => { - const { deltas, pcts, decreased } = files[file]; + const { deltas, pcts, decreased, belowThreshold, isNewFile } = files[file]; const row = [ - decreased ? '🔴' : '✅', - file, + decreased || belowThreshold ? '🔴' : '✅', + `${isNewFile ? '✨ ' : ''}${file}`, `${pcts.lines}%
(${formatDelta(deltas.lines)})`, `${pcts.branches}%
(${formatDelta(deltas.branches)})`, `${pcts.functions}%
(${formatDelta(deltas.functions)})`, diff --git a/src/summaries.fixture.ts b/src/summaries.fixture.ts index 8a991eb..d072ecc 100644 --- a/src/summaries.fixture.ts +++ b/src/summaries.fixture.ts @@ -2,6 +2,7 @@ import { JsonSummary } from './common'; export const fileFullCovered: JsonSummary = { total: { + isNewFile: false, lines: { total: 2, covered: 2, @@ -28,6 +29,7 @@ export const fileFullCovered: JsonSummary = { } }, fileA: { + isNewFile: false, lines: { total: 2, covered: 2, @@ -58,6 +60,7 @@ export const fileFullCovered: JsonSummary = { export const fileFullCoveredfileHalfCovered: JsonSummary = { ...fileFullCovered, fileB: { + isNewFile: false, lines: { total: 2, covered: 1, @@ -84,6 +87,7 @@ export const fileFullCoveredfileHalfCovered: JsonSummary = { } }, total: { + isNewFile: false, lines: { total: 4, covered: 3, @@ -113,6 +117,7 @@ export const fileFullCoveredfileHalfCovered: JsonSummary = { export const fileNotCovered: JsonSummary = { total: { + isNewFile: false, lines: { total: 2, covered: 0, @@ -139,6 +144,7 @@ export const fileNotCovered: JsonSummary = { } }, fileA: { + isNewFile: false, lines: { total: 2, covered: 0, @@ -168,6 +174,7 @@ export const fileNotCovered: JsonSummary = { export const fileHalfCovered: JsonSummary = { total: { + isNewFile: false, lines: { total: 2, covered: 1, @@ -194,6 +201,7 @@ export const fileHalfCovered: JsonSummary = { } }, fileA: { + isNewFile: false, lines: { total: 2, covered: 1, @@ -224,6 +232,7 @@ export const fileHalfCovered: JsonSummary = { export const coverageNotChanged: JsonSummary = { ...fileFullCovered, fileA: { + isNewFile: false, lines: { total: 2, covered: 1, @@ -253,6 +262,7 @@ export const coverageNotChanged: JsonSummary = { export const coverageDecreased: JsonSummary = { total: { + isNewFile: false, lines: { total: 0, covered: 1, @@ -279,6 +289,7 @@ export const coverageDecreased: JsonSummary = { } }, fileA: { + isNewFile: false, lines: { total: 0, covered: -1, @@ -309,6 +320,7 @@ export const coverageDecreased: JsonSummary = { export const totalDecreased: JsonSummary = { ...coverageNotChanged, total: { + isNewFile: false, lines: { total: 2, covered: 1, @@ -349,9 +361,80 @@ export const onlyLinesIncreased: JsonSummary = { } }; -export const newFile: JsonSummary = { +export const newFile: JsonSummary ={ ...fileFullCovered, fileB: { ...fileFullCovered.fileA } }; + +export const newFileNotCovered: JsonSummary = { + ...fileFullCovered, + total: { + isNewFile: false, + lines: { + total: 4, + covered: 2, + skipped: 0, + pct: 50 + }, + statements: { + total: 4, + covered: 2, + skipped: 0, + pct: 50 + }, + functions: { + total: 4, + covered: 2, + skipped: 0, + pct: 50 + }, + branches: { + total: 4, + covered: 2, + skipped: 0, + pct: 50 + } + }, + fileB: { + ...fileNotCovered.fileA, + isNewFile: true + } +}; + + +export const newFileHalfCovered: JsonSummary = { + ...fileFullCovered, + total: { + isNewFile: false, + lines: { + total: 4, + covered: 3, + skipped: 0, + pct: 75 + }, + statements: { + total: 4, + covered: 3, + skipped: 0, + pct: 75 + }, + functions: { + total: 4, + covered: 3, + skipped: 0, + pct: 75 + }, + branches: { + total: 4, + covered: 3, + skipped: 0, + pct: 75 + } + }, + fileB: { + ...fileHalfCovered.fileA, + isNewFile: true + } +}; From 13e27d9fec77b9b3f2585b11465d8a6a29a279c8 Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Mon, 27 Jun 2022 17:08:53 -0500 Subject: [PATCH 02/10] update snapshots for new file functionality --- src/__snapshots__/coverageDiffer.test.ts.snap | 7 +++++++ src/__snapshots__/resultFormatter.test.ts.snap | 10 ++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/__snapshots__/coverageDiffer.test.ts.snap b/src/__snapshots__/coverageDiffer.test.ts.snap index ea619e1..685d6d5 100644 --- a/src/__snapshots__/coverageDiffer.test.ts.snap +++ b/src/__snapshots__/coverageDiffer.test.ts.snap @@ -15,6 +15,7 @@ Object { "skipped": 0, "total": 0, }, + "isNewFile": false, "lines": Object { "covered": -1, "pct": -50, @@ -41,6 +42,7 @@ Object { "skipped": 0, "total": 0, }, + "isNewFile": false, "lines": Object { "covered": -1, "pct": -50, @@ -72,6 +74,7 @@ Object { "skipped": 0, "total": 0, }, + "isNewFile": false, "lines": Object { "covered": 1, "pct": 50, @@ -98,6 +101,7 @@ Object { "skipped": 0, "total": 0, }, + "isNewFile": false, "lines": Object { "covered": 1, "pct": 50, @@ -129,6 +133,7 @@ Object { "skipped": 0, "total": 0, }, + "isNewFile": false, "lines": Object { "covered": 0, "pct": 0, @@ -155,6 +160,7 @@ Object { "skipped": 0, "total": 2, }, + "isNewFile": true, "lines": Object { "covered": 2, "pct": 100, @@ -181,6 +187,7 @@ Object { "skipped": 0, "total": 0, }, + "isNewFile": false, "lines": Object { "covered": 0, "pct": 0, diff --git a/src/__snapshots__/resultFormatter.test.ts.snap b/src/__snapshots__/resultFormatter.test.ts.snap index d4406c2..775024c 100644 --- a/src/__snapshots__/resultFormatter.test.ts.snap +++ b/src/__snapshots__/resultFormatter.test.ts.snap @@ -1,10 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`resultFormatter should format files results as markdown table 1`] = ` -"| Ok | File | Lines | Branches | Functions | Statements | -| -- | ----- | ------------- | ------------- | ------------ | ------------- | -| 🔴 | file1 | 80%
(+10%) | 14%
(-30%) | 3%
(+20%) | 20%
(-10%) | -| ✅ | file2 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +"| Ok | File (✨=New File) | Lines | Branches | Functions | Statements | +| -- | ----------------- | ------------- | ------------- | ------------ | ------------- | +| 🔴 | file1 | 80%
(+10%) | 14%
(-30%) | 3%
(+20%) | 20%
(-10%) | +| ✅ | file2 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| 🔴 | file3 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| ✅ | ✨ file4 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | Total: From 79fb2d5bd12fa034022f1423744f674d14f719e4 Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Mon, 27 Jun 2022 17:18:26 -0500 Subject: [PATCH 03/10] update docs --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4b7a5b9..e915c06 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ - Formatted as markdown table - Fail if coverage decreases on a file (check on percentage) for any of the lines/func/statements/branches. Can  be configured to only check some criteria. +- Separate threshold for new files `newFileCoverageThreshold`, defaults to `coverageThreshold` if not passed - Written in Typescript. ## Usage From d563c6678b995e92f4d631108263ed0546c6869f Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Mon, 27 Jun 2022 17:18:36 -0500 Subject: [PATCH 04/10] actually pass in newFileCoverageThreshold --- src/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 721c0f1..6fbe2fe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,7 +17,7 @@ export function diff( head: JsonSummary, options = defaultOptions ): CoverageDiffOutput { - const { checkCriteria, coverageThreshold, coverageDecreaseThreshold } = + const { checkCriteria, coverageThreshold, coverageDecreaseThreshold, newFileCoverageThreshold } = options; const { regression, files, totals, diff, belowThreshold } = diffChecker( @@ -25,7 +25,8 @@ export function diff( head, checkCriteria, coverageThreshold, - coverageDecreaseThreshold + coverageDecreaseThreshold, + newFileCoverageThreshold ); const results = resultFormatter(files, totals); From df2b7d03aef0f2f69d51a4869ef88ede9100e1e6 Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Thu, 30 Jun 2022 14:14:11 -0500 Subject: [PATCH 05/10] remove .only --- src/diffChecker.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diffChecker.test.ts b/src/diffChecker.test.ts index a695b6a..c1dfc3a 100644 --- a/src/diffChecker.test.ts +++ b/src/diffChecker.test.ts @@ -251,7 +251,7 @@ describe('diffChecker', () => { expect(result.regression).toBe(false); }); - it.only('should be below threshold', () => { + it('should be below threshold', () => { // Total is now 75% but file threshold is 60% so it should be belowThreshold expect(result.belowThreshold).toBe(true); }); From 32c33ee1bca16953503f4a8789aa5983a2c10f6f Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Thu, 30 Jun 2022 14:21:34 -0500 Subject: [PATCH 06/10] fix failing tests --- src/diffChecker.test.ts | 8 ++++---- src/index.test.ts | 26 ++++++-------------------- 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/src/diffChecker.test.ts b/src/diffChecker.test.ts index c1dfc3a..4642c20 100644 --- a/src/diffChecker.test.ts +++ b/src/diffChecker.test.ts @@ -215,7 +215,7 @@ describe('diffChecker', () => { }); it('should be below threshold', () => { - // Total is now 50% but file threshold is 40%, and new file threshold is 40, so it should be below the threshold + // Total is now 50% but file threshold is 40%, and new file threshold is 40, new file is below threshold, global is above threshold expect(result.belowThreshold).toBe(true); }); @@ -252,7 +252,7 @@ describe('diffChecker', () => { }); it('should be below threshold', () => { - // Total is now 75% but file threshold is 60% so it should be belowThreshold + // Total is now 75% but file threshold is 60%, new file is below threshold, global is above threshold expect(result.belowThreshold).toBe(true); }); @@ -289,8 +289,8 @@ describe('diffChecker', () => { }); it('should not be below threshold', () => { - // Total is now 50% but file threshold is 40%, and new file threshold is 45, so it should be above the threshold - expect(result.belowThreshold).toBe(false); + // Total is now 50% but file threshold is 40%, and new file threshold is 45, new file is below threshold, global is above threshold + expect(result.belowThreshold).toBe(true); }); it('outputs correct total percentages', () => { diff --git a/src/index.test.ts b/src/index.test.ts index 66feb9d..ae96253 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -24,7 +24,8 @@ describe('diff', () => { fileFullCovered, coverageDiff.defaultOptions.checkCriteria, coverageDiff.defaultOptions.coverageThreshold, - coverageDiff.defaultOptions.coverageDecreaseThreshold + coverageDiff.defaultOptions.coverageDecreaseThreshold, + coverageDiff.defaultOptions.newFileCoverageThreshold // will be undefined - defaults to coverageThreshold in diffChecker ); }); @@ -48,7 +49,8 @@ describe('diff', () => { const mockedOptions: ConfigOptions = { checkCriteria: ['lines'], coverageThreshold: 100, - coverageDecreaseThreshold: 0 + coverageDecreaseThreshold: 0, + newFileCoverageThreshold: 1 }; coverageDiff.diff(fileNotCovered, fileFullCovered, mockedOptions); @@ -58,26 +60,10 @@ describe('diff', () => { fileFullCovered, mockedOptions.checkCriteria, mockedOptions.coverageThreshold, - mockedOptions.coverageDecreaseThreshold + mockedOptions.coverageDecreaseThreshold, + mockedOptions.newFileCoverageThreshold, ); }); - it('should call the diffChecker module with deprecated option', () => { - const mockedOptions: ConfigOptions = { - checkCriteria: ['lines'], - coverageThreshold: 100, - coverageDecreaseThreshold: 0 - }; - - coverageDiff.diff(fileNotCovered, fileFullCovered, mockedOptions); - - expect(diffCheckerSpy).toHaveBeenCalledWith( - fileNotCovered, - fileFullCovered, - mockedOptions.checkCriteria, - mockedOptions.coverageThreshold, - mockedOptions.coverageDecreaseThreshold - ); - }); }); }); From 1f13e1db553fe1e5ffc3614f99e1743f02d5391a Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Thu, 30 Jun 2022 15:16:20 -0500 Subject: [PATCH 07/10] cleanup diffChecker --- src/diffChecker.ts | 90 +++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/src/diffChecker.ts b/src/diffChecker.ts index e39431d..08c0837 100644 --- a/src/diffChecker.ts +++ b/src/diffChecker.ts @@ -27,60 +27,63 @@ export const diffChecker = ( const diff = coverageDiffer(base, head); const diffMap = objectToMap(diff); const percentageMap: Map = new Map(); - const nonZeroTest = (x: number) => x !== 0; const coverageDecreased = (x: number) => x < 0 ? Math.abs(x) >= coverageDecreaseThreshold : false; - const isBelowThreshold = (x: number) => x < coverageThreshold; - const isBelowNewFileThreshold = (x: number) => x < newFileCoverageThreshold; + const isBelowThreshold = (x: number) => x < coverageThreshold; + const isBelowNewFileThreshold = (x: number) => x < newFileCoverageThreshold; - diffMap.forEach((v, k) => { - const diffPercentages = getSummaryPercentages(v); + const checkItemBelowThreshold = (diff: CoverageSummary, coverageToCompare: CoverageSummary, checkCriteria: Criteria[]) => { + const condition = diff.isNewFile + ? isBelowNewFileThreshold + : isBelowThreshold; + return checkCoverageForCondition( + coverageToCompare, + checkCriteria, + condition + ); + } - let itemBelowThreshold = false; - let decreased = false; + const checkItemDecreased = ( + diff: CoverageSummary, + checkCriteria: Criteria[] + ) => { + if (diff.isNewFile) return false; + return checkCoverageForCondition(diff, checkCriteria, coverageDecreased); + }; - // Only check files that changed coverage. or new files - if (v.isNewFile) { - itemBelowThreshold = checkCoverageForCondition( - head[k], - checkCriteria, - isBelowNewFileThreshold - ); - } else if (Object.values(diffPercentages).some(nonZeroTest)) { - decreased = checkCoverageForCondition( - v, - checkCriteria, - coverageDecreased - ); - itemBelowThreshold = checkCoverageForCondition( - head[k], - checkCriteria, - isBelowThreshold - ); - } else { + + diffMap.forEach((diff, fileName) => { + const diffPercentages = getSummaryPercentages(diff); + if (shouldExcludeItem(diff, diffPercentages)) { return; } - // Ignore the total field as we check only files. - if (k !== 'total') { - // Coverage decreased on a file or under threshold, regress. - if (decreased) { + const itemDecreased = checkItemDecreased(diff, checkCriteria); + const itemBelowThreshold = checkItemBelowThreshold(diff, head[fileName], checkCriteria) + + // Coverage decreased on a file, regress. + // only check file specific regressions, ignore regressions in the total, regression should still be set + // if any non-new file was changed + if (fileName !== 'total') { + if (itemDecreased) { regression = true; } - if (itemBelowThreshold) { - belowThreshold = true; - } + } + // If Total or any file is below threshold, return belowThreshold as true + if (itemBelowThreshold) { + belowThreshold = true; } - percentageMap.set(k, { + percentageMap.set(fileName, { deltas: { ...diffPercentages }, - pcts: getSummaryPercentages(head[k]), - decreased, + pcts: getSummaryPercentages(head[fileName]), + isNewFile: diff.isNewFile, + decreased: itemDecreased, belowThreshold: itemBelowThreshold, - isNewFile: v.isNewFile }); + }); let totals = percentageMap.get('total'); @@ -127,3 +130,16 @@ const checkCoverageForCondition = ( return values.some(condition); }; + +const zeroTest = (x: number) => x === 0; + +const shouldExcludeItem = (diff: CoverageSummary, diffPercentages: ReturnType) => { + if (diff.isNewFile) { + return false; + } + else { + // if every value is zero, exclude the item from the diff because nothing has changed + return Object.values(diffPercentages).every(zeroTest) + } +} + From 891be874c1956d6ad5cdcbb78c0b8bb00f73f917 Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Thu, 30 Jun 2022 15:19:03 -0500 Subject: [PATCH 08/10] format files --- src/coverageDiffer.ts | 2 +- src/diffChecker.test.ts | 4 ++-- src/diffChecker.ts | 31 +++++++++++++++++++------------ src/index.test.ts | 3 +-- src/index.ts | 8 ++++++-- src/resultFormatter.ts | 9 ++++++++- src/summaries.fixture.ts | 3 +-- 7 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/coverageDiffer.ts b/src/coverageDiffer.ts index 8a62c17..34e0e22 100644 --- a/src/coverageDiffer.ts +++ b/src/coverageDiffer.ts @@ -22,7 +22,7 @@ export const coverageDiffer = ( diffMap.set(k, diffSummary(v, fileSummary)); } else { // New file. - diffMap.set(k, {...v, isNewFile: true}); + diffMap.set(k, { ...v, isNewFile: true }); } }); diff --git a/src/diffChecker.test.ts b/src/diffChecker.test.ts index 4642c20..1c93917 100644 --- a/src/diffChecker.test.ts +++ b/src/diffChecker.test.ts @@ -259,7 +259,7 @@ describe('diffChecker', () => { it('outputs correct total percentages', () => { expectToMatchObject(result.totals, { belowThreshold: false, // Threshold is 60, total is 75, total is not below, but file is - decreased: false, + decreased: false, pcts: { branches: 75, functions: 75, @@ -296,7 +296,7 @@ describe('diffChecker', () => { it('outputs correct total percentages', () => { expectToMatchObject(result.totals, { belowThreshold: false, // Threshold is 40, total is 50 - decreased: false, + decreased: false, pcts: { branches: 50, functions: 50, diff --git a/src/diffChecker.ts b/src/diffChecker.ts index 08c0837..07c63a1 100644 --- a/src/diffChecker.ts +++ b/src/diffChecker.ts @@ -32,7 +32,11 @@ export const diffChecker = ( const isBelowThreshold = (x: number) => x < coverageThreshold; const isBelowNewFileThreshold = (x: number) => x < newFileCoverageThreshold; - const checkItemBelowThreshold = (diff: CoverageSummary, coverageToCompare: CoverageSummary, checkCriteria: Criteria[]) => { + const checkItemBelowThreshold = ( + diff: CoverageSummary, + coverageToCompare: CoverageSummary, + checkCriteria: Criteria[] + ) => { const condition = diff.isNewFile ? isBelowNewFileThreshold : isBelowThreshold; @@ -41,7 +45,7 @@ export const diffChecker = ( checkCriteria, condition ); - } + }; const checkItemDecreased = ( diff: CoverageSummary, @@ -51,7 +55,6 @@ export const diffChecker = ( return checkCoverageForCondition(diff, checkCriteria, coverageDecreased); }; - diffMap.forEach((diff, fileName) => { const diffPercentages = getSummaryPercentages(diff); if (shouldExcludeItem(diff, diffPercentages)) { @@ -59,7 +62,11 @@ export const diffChecker = ( } const itemDecreased = checkItemDecreased(diff, checkCriteria); - const itemBelowThreshold = checkItemBelowThreshold(diff, head[fileName], checkCriteria) + const itemBelowThreshold = checkItemBelowThreshold( + diff, + head[fileName], + checkCriteria + ); // Coverage decreased on a file, regress. // only check file specific regressions, ignore regressions in the total, regression should still be set @@ -81,9 +88,8 @@ export const diffChecker = ( pcts: getSummaryPercentages(head[fileName]), isNewFile: diff.isNewFile, decreased: itemDecreased, - belowThreshold: itemBelowThreshold, + belowThreshold: itemBelowThreshold }); - }); let totals = percentageMap.get('total'); @@ -133,13 +139,14 @@ const checkCoverageForCondition = ( const zeroTest = (x: number) => x === 0; -const shouldExcludeItem = (diff: CoverageSummary, diffPercentages: ReturnType) => { +const shouldExcludeItem = ( + diff: CoverageSummary, + diffPercentages: ReturnType +) => { if (diff.isNewFile) { return false; - } - else { + } else { // if every value is zero, exclude the item from the diff because nothing has changed - return Object.values(diffPercentages).every(zeroTest) + return Object.values(diffPercentages).every(zeroTest); } -} - +}; diff --git a/src/index.test.ts b/src/index.test.ts index ae96253..08994e1 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -61,9 +61,8 @@ describe('diff', () => { mockedOptions.checkCriteria, mockedOptions.coverageThreshold, mockedOptions.coverageDecreaseThreshold, - mockedOptions.newFileCoverageThreshold, + mockedOptions.newFileCoverageThreshold ); }); - }); }); diff --git a/src/index.ts b/src/index.ts index 6fbe2fe..a89593e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,8 +17,12 @@ export function diff( head: JsonSummary, options = defaultOptions ): CoverageDiffOutput { - const { checkCriteria, coverageThreshold, coverageDecreaseThreshold, newFileCoverageThreshold } = - options; + const { + checkCriteria, + coverageThreshold, + coverageDecreaseThreshold, + newFileCoverageThreshold + } = options; const { regression, files, totals, diff, belowThreshold } = diffChecker( base, diff --git a/src/resultFormatter.ts b/src/resultFormatter.ts index d68da8d..a95b416 100644 --- a/src/resultFormatter.ts +++ b/src/resultFormatter.ts @@ -33,7 +33,14 @@ const formatTotal = (total: FileResultFormat): string => { const formatFilesResults = (files: FilesResults): string => { let noChange = true; const table: Array<(string | number)[]> = []; - const header = ['Ok', 'File (✨=New File)', 'Lines', 'Branches', 'Functions', 'Statements']; + const header = [ + 'Ok', + 'File (✨=New File)', + 'Lines', + 'Branches', + 'Functions', + 'Statements' + ]; table.push(header); Object.keys(files).forEach((file) => { diff --git a/src/summaries.fixture.ts b/src/summaries.fixture.ts index d072ecc..6bb59a2 100644 --- a/src/summaries.fixture.ts +++ b/src/summaries.fixture.ts @@ -361,7 +361,7 @@ export const onlyLinesIncreased: JsonSummary = { } }; -export const newFile: JsonSummary ={ +export const newFile: JsonSummary = { ...fileFullCovered, fileB: { ...fileFullCovered.fileA @@ -403,7 +403,6 @@ export const newFileNotCovered: JsonSummary = { } }; - export const newFileHalfCovered: JsonSummary = { ...fileFullCovered, total: { From 3af0112ecf94a3fa0647cca3a8fa5abc1d7ea0e0 Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Thu, 30 Jun 2022 15:33:14 -0500 Subject: [PATCH 09/10] remove new Emojji and replace with (New) and add reason to OK column --- .../resultFormatter.test.ts.snap | 61 +++++++++++++++++-- src/resultFormatter.test.ts | 29 +++++++++ src/resultFormatter.ts | 32 +++++++--- 3 files changed, 109 insertions(+), 13 deletions(-) diff --git a/src/__snapshots__/resultFormatter.test.ts.snap b/src/__snapshots__/resultFormatter.test.ts.snap index 775024c..51500fd 100644 --- a/src/__snapshots__/resultFormatter.test.ts.snap +++ b/src/__snapshots__/resultFormatter.test.ts.snap @@ -1,12 +1,45 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`resultFormatter should default to coverageThreshold for newFileCoverageThreshold 1`] = ` +"| Ok (reason) | File | Lines | Branches | Functions | Statements | +| ----------------------- | ----------- | ------------- | ------------- | ------------ | ------------- | +| 🔴
(Decreased >2%) | file1 | 80%
(+10%) | 14%
(-30%) | 3%
(+20%) | 20%
(-10%) | +| ✅ | file2 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| 🔴
(Below 1%) | file3 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| ✅ | (New) file4 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| 🔴
(Below 1%) | (New) file5 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | + +Total: + +| Lines | Branches | Functions | Statements | +| ----------- | ----------- | ----------- | ----------- | +| 100%(+100%) | 100%(+100%) | 100%(+100%) | 100%(+100%) |" +`; + exports[`resultFormatter should format files results as markdown table 1`] = ` -"| Ok | File (✨=New File) | Lines | Branches | Functions | Statements | -| -- | ----------------- | ------------- | ------------- | ------------ | ------------- | -| 🔴 | file1 | 80%
(+10%) | 14%
(-30%) | 3%
(+20%) | 20%
(-10%) | -| ✅ | file2 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | -| 🔴 | file3 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | -| ✅ | ✨ file4 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +"| Ok (reason) | File | Lines | Branches | Functions | Statements | +| ----------------------- | ----------- | ------------- | ------------- | ------------ | ------------- | +| 🔴
(Decreased >2%) | file1 | 80%
(+10%) | 14%
(-30%) | 3%
(+20%) | 20%
(-10%) | +| ✅ | file2 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| 🔴
(Below 3%) | file3 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| ✅ | (New) file4 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| 🔴
(Below 1%) | (New) file5 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | + +Total: + +| Lines | Branches | Functions | Statements | +| ----------- | ----------- | ----------- | ----------- | +| 100%(+100%) | 100%(+100%) | 100%(+100%) | 100%(+100%) |" +`; + +exports[`resultFormatter should format files results as markdown table with defaults 1`] = ` +"| Ok (reason) | File | Lines | Branches | Functions | Statements | +| ----------------------- | ----------- | ------------- | ------------- | ------------ | ------------- | +| 🔴
(Decreased >0%) | file1 | 80%
(+10%) | 14%
(-30%) | 3%
(+20%) | 20%
(-10%) | +| ✅ | file2 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| 🔴
(Below 100%) | file3 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| ✅ | (New) file4 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| 🔴
(Below 100%) | (New) file5 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | Total: @@ -24,3 +57,19 @@ Total: | ----------- | ----------- | ----------- | ----------- | | 100%(+100%) | 100%(+100%) | 100%(+100%) | 100%(+100%) |" `; + +exports[`resultFormatter should use defaults 1`] = ` +"| Ok (reason) | File | Lines | Branches | Functions | Statements | +| ----------------------- | ----------- | ------------- | ------------- | ------------ | ------------- | +| 🔴
(Decreased >0%) | file1 | 80%
(+10%) | 14%
(-30%) | 3%
(+20%) | 20%
(-10%) | +| ✅ | file2 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| 🔴
(Below 100%) | file3 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| ✅ | (New) file4 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | +| 🔴
(Below 100%) | (New) file5 | 20%
(+10%) | 8%
(+30%) | 2%
(+20%) | 5%
(+10%) | + +Total: + +| Lines | Branches | Functions | Statements | +| ----------- | ----------- | ----------- | ----------- | +| 100%(+100%) | 100%(+100%) | 100%(+100%) | 100%(+100%) |" +`; diff --git a/src/resultFormatter.test.ts b/src/resultFormatter.test.ts index 8473441..95dbf42 100644 --- a/src/resultFormatter.test.ts +++ b/src/resultFormatter.test.ts @@ -69,6 +69,23 @@ const filesResults: FilesResults = { }, decreased: false, belowThreshold: false + }, + file5: { + isNewFile: true, + deltas: { + lines: 10, + statements: 10, + functions: 20, + branches: 30 + }, + pcts: { + lines: 20, + statements: 5, + functions: 2, + branches: 8 + }, + decreased: false, + belowThreshold: true } }; @@ -92,6 +109,18 @@ const totalResults: FileResultFormat = { describe('resultFormatter', () => { it('should format files results as markdown table', () => { + expect(resultFormatter(filesResults, totalResults, 1, 2, 3)).toMatchSnapshot(); + }); + + it('should use defaults', () => { + expect(resultFormatter(filesResults, totalResults)).toMatchSnapshot(); + }); + + it('should default to coverageThreshold for newFileCoverageThreshold', () => { + expect(resultFormatter(filesResults, totalResults, 1, 2)).toMatchSnapshot(); + }); + + it('should format files results as markdown table with defaults', () => { expect(resultFormatter(filesResults, totalResults)).toMatchSnapshot(); }); diff --git a/src/resultFormatter.ts b/src/resultFormatter.ts index a95b416..701ac71 100644 --- a/src/resultFormatter.ts +++ b/src/resultFormatter.ts @@ -1,11 +1,18 @@ import markdownTable from 'markdown-table'; import { FilesResults, FileResultFormat } from './common'; +import { defaultOptions } from './index'; export const resultFormatter = ( files: FilesResults, - total: FileResultFormat + total: FileResultFormat, + coverageThreshold = defaultOptions.coverageThreshold!, + coverageDecreaseThreshold = defaultOptions.coverageDecreaseThreshold!, + newFileCoverageThreshold = coverageThreshold ): string => { - const formattedFiles = formatFilesResults(files); + const formattedFiles = formatFilesResults(files, + coverageThreshold, + coverageDecreaseThreshold, + newFileCoverageThreshold); const formattedTotal = formatTotal(total); return `${formattedFiles}${formattedTotal}`; }; @@ -30,12 +37,15 @@ const formatTotal = (total: FileResultFormat): string => { return '\n\nTotal:\n\n' + markdownTable(table); }; -const formatFilesResults = (files: FilesResults): string => { +const formatFilesResults = (files: FilesResults, + coverageThreshold = defaultOptions.coverageThreshold!, + coverageDecreaseThreshold = defaultOptions.coverageDecreaseThreshold!, + newFileCoverageThreshold = coverageThreshold): string => { let noChange = true; const table: Array<(string | number)[]> = []; const header = [ - 'Ok', - 'File (✨=New File)', + 'Ok (reason)', + 'File', 'Lines', 'Branches', 'Functions', @@ -45,9 +55,17 @@ const formatFilesResults = (files: FilesResults): string => { Object.keys(files).forEach((file) => { const { deltas, pcts, decreased, belowThreshold, isNewFile } = files[file]; + const reasons = []; + if (belowThreshold) { + reasons.push(`Below ${isNewFile ? coverageThreshold : newFileCoverageThreshold}%`); + } + if (decreased) { + reasons.push(`Decreased >${coverageDecreaseThreshold}%`) + } + const row = [ - decreased || belowThreshold ? '🔴' : '✅', - `${isNewFile ? '✨ ' : ''}${file}`, + decreased || belowThreshold ? `🔴
(${reasons.join(" & ")})` : '✅', + `${isNewFile ? '(New) ' : ''}${file}`, `${pcts.lines}%
(${formatDelta(deltas.lines)})`, `${pcts.branches}%
(${formatDelta(deltas.branches)})`, `${pcts.functions}%
(${formatDelta(deltas.functions)})`, From 595737c61b24b62ed28a5758ced8657b102c1c3b Mon Sep 17 00:00:00 2001 From: Nick Bollesyarn Date: Fri, 1 Jul 2022 16:38:12 -0500 Subject: [PATCH 10/10] fix lint issues --- src/resultFormatter.test.ts | 42 +++++-------------------------------- src/resultFormatter.ts | 20 +++++++++++------- 2 files changed, 18 insertions(+), 44 deletions(-) diff --git a/src/resultFormatter.test.ts b/src/resultFormatter.test.ts index 36e69a0..0d81668 100644 --- a/src/resultFormatter.test.ts +++ b/src/resultFormatter.test.ts @@ -70,40 +70,6 @@ const filesResults: FilesResults = { decreased: false, belowThreshold: false }, - file3: { - isNewFile: false, - deltas: { - lines: 10, - statements: 10, - functions: 20, - branches: 30 - }, - pcts: { - lines: 20, - statements: 5, - functions: 2, - branches: 8 - }, - decreased: false, - belowThreshold: true - }, - file4: { - isNewFile: true, - deltas: { - lines: 10, - statements: 10, - functions: 20, - branches: 30 - }, - pcts: { - lines: 20, - statements: 5, - functions: 2, - branches: 8 - }, - decreased: false, - belowThreshold: false - }, file5: { isNewFile: true, deltas: { @@ -143,13 +109,15 @@ const totalResults: FileResultFormat = { describe('resultFormatter', () => { it('should format files results as markdown table', () => { - expect(resultFormatter(filesResults, totalResults, 1, 2, 3)).toMatchSnapshot(); + expect( + resultFormatter(filesResults, totalResults, 1, 2, 3) + ).toMatchSnapshot(); }); - + it('should use defaults', () => { expect(resultFormatter(filesResults, totalResults)).toMatchSnapshot(); }); - + it('should default to coverageThreshold for newFileCoverageThreshold', () => { expect(resultFormatter(filesResults, totalResults, 1, 2)).toMatchSnapshot(); }); diff --git a/src/resultFormatter.ts b/src/resultFormatter.ts index 701ac71..53526f8 100644 --- a/src/resultFormatter.ts +++ b/src/resultFormatter.ts @@ -9,10 +9,12 @@ export const resultFormatter = ( coverageDecreaseThreshold = defaultOptions.coverageDecreaseThreshold!, newFileCoverageThreshold = coverageThreshold ): string => { - const formattedFiles = formatFilesResults(files, + const formattedFiles = formatFilesResults( + files, coverageThreshold, coverageDecreaseThreshold, - newFileCoverageThreshold); + newFileCoverageThreshold + ); const formattedTotal = formatTotal(total); return `${formattedFiles}${formattedTotal}`; }; @@ -37,10 +39,12 @@ const formatTotal = (total: FileResultFormat): string => { return '\n\nTotal:\n\n' + markdownTable(table); }; -const formatFilesResults = (files: FilesResults, +const formatFilesResults = ( + files: FilesResults, coverageThreshold = defaultOptions.coverageThreshold!, coverageDecreaseThreshold = defaultOptions.coverageDecreaseThreshold!, - newFileCoverageThreshold = coverageThreshold): string => { + newFileCoverageThreshold = coverageThreshold +): string => { let noChange = true; const table: Array<(string | number)[]> = []; const header = [ @@ -57,14 +61,16 @@ const formatFilesResults = (files: FilesResults, const { deltas, pcts, decreased, belowThreshold, isNewFile } = files[file]; const reasons = []; if (belowThreshold) { - reasons.push(`Below ${isNewFile ? coverageThreshold : newFileCoverageThreshold}%`); + reasons.push( + `Below ${isNewFile ? coverageThreshold : newFileCoverageThreshold}%` + ); } if (decreased) { - reasons.push(`Decreased >${coverageDecreaseThreshold}%`) + reasons.push(`Decreased >${coverageDecreaseThreshold}%`); } const row = [ - decreased || belowThreshold ? `🔴
(${reasons.join(" & ")})` : '✅', + decreased || belowThreshold ? `🔴
(${reasons.join(' & ')})` : '✅', `${isNewFile ? '(New) ' : ''}${file}`, `${pcts.lines}%
(${formatDelta(deltas.lines)})`, `${pcts.branches}%
(${formatDelta(deltas.branches)})`,