danger-plugin-coverage
Advanced tools
Comparing version
@@ -57,9 +57,33 @@ "use strict"; | ||
methods, | ||
coveredmethods | ||
coveredmethods, | ||
lines, | ||
coveredlines | ||
}) => ({ | ||
statements: getCoveredPercentage(coveredstatements, statements), | ||
branches: getCoveredPercentage(coveredconditionals, conditionals), | ||
functions: getCoveredPercentage(coveredmethods, methods) | ||
functions: getCoveredPercentage(coveredmethods, methods), | ||
lines: getCoveredPercentage(coveredlines, lines) | ||
}); | ||
/** | ||
* Get the metrics for a file. | ||
*/ | ||
const getFileMetrics = file => { | ||
const { | ||
line: lines = [], | ||
metrics | ||
} = file; | ||
const fileMetrics = (metrics === null || metrics === void 0 ? void 0 : metrics[0].$) || {}; | ||
const uncoveredLines = lines.filter(line => { | ||
var _line$$; | ||
return !Number(((_line$$ = line.$) === null || _line$$ === void 0 ? void 0 : _line$$.count) || 0); | ||
}); | ||
return { ...fileMetrics, | ||
lines: lines.length, | ||
coveredlines: lines.length - uncoveredLines.length | ||
}; | ||
}; | ||
/** | ||
* Shorten a path so that it fits in a GitHub comment. | ||
@@ -100,4 +124,5 @@ */ | ||
branches, | ||
functions | ||
}) => (Number(statements) >= threshold.statements || statements === '-') && (Number(branches) >= threshold.branches || branches === '-') && (Number(functions) >= threshold.functions || functions === '-'); | ||
functions, | ||
lines | ||
}) => (Number(statements) >= threshold.statements || statements === '-') && (Number(branches) >= threshold.branches || branches === '-') && (Number(functions) >= threshold.functions || functions === '-') && (Number(lines) >= threshold.lines || lines === '-'); | ||
/** | ||
@@ -111,9 +136,4 @@ * Build a row for the coverage table. | ||
const fileMetrics = getFileMetrics(file); | ||
const { | ||
line = [], | ||
metrics | ||
} = file; | ||
const fileMetrics = (metrics === null || metrics === void 0 ? void 0 : metrics[0].$) || {}; | ||
const noLines = !line.length; | ||
const { | ||
sha | ||
@@ -128,7 +148,3 @@ } = ((_danger$git = danger.git) === null || _danger$git === void 0 ? void 0 : (_danger$git$commits = _danger$git.commits) === null || _danger$git$commits === void 0 ? void 0 : _danger$git$commits[danger.git.commits.length - 1]) || {}; | ||
const percentages = getMetricPercentages(fileMetrics); | ||
const { | ||
statements, | ||
branches, | ||
functions | ||
} = percentages; | ||
const noLines = !fileMetrics.lines; | ||
let emoji = hasPassed(threshold, percentages) ? ':white_check_mark:' : ':x:'; | ||
@@ -140,3 +156,3 @@ | ||
return ['', fileCell, noLines ? '-' : statements, noLines ? '-' : branches, noLines ? '-' : functions, emoji, ''].join('|'); | ||
return ['', fileCell, noLines ? '-' : percentages.statements, noLines ? '-' : percentages.branches, noLines ? '-' : percentages.functions, noLines ? '-' : percentages.lines, emoji, ''].join('|'); | ||
}; | ||
@@ -154,6 +170,5 @@ /** | ||
const buildTable = (files, maxRows, threshold) => { | ||
const headings = ['Impacted Files', '% Stmts', '% Branch', '% Funcs', '']; | ||
const buildTable = (files, maxRows, threshold, showAllFiles) => { | ||
const headings = [`${showAllFiles ? '' : 'Impacted '}Files`, '% Stmts', '% Branch', '% Funcs', '% Lines', '']; | ||
const headingRow = joinRow(headings); | ||
const emptyHeadingRow = joinRow(new Array(headings.length).fill(' ')); | ||
const seperator = joinRow(new Array(headings.length).fill().reduce((acc, _, index) => [...acc, index === 0 ? '---' : ':-:' // Center align all but the first column | ||
@@ -167,3 +182,3 @@ ], [])); | ||
if (extraFileRows.length) { | ||
table += [newLine, '<details>', '<summary>', `and ${extraFileRows.length} more...`, '</summary>', '', emptyHeadingRow, seperator, ...extraFileRows, '</details>'].join(newLine); | ||
table += [newLine, '<details>', '<summary>', `and ${extraFileRows.length} more...`, '</summary>', '', headingRow, seperator, ...extraFileRows, '</details>'].join(newLine); | ||
} | ||
@@ -179,3 +194,3 @@ | ||
const getThresholdSummaryLine = (percentages, key, threshold) => { | ||
const wasMet = Number(percentages[key]) >= threshold[key]; | ||
const wasMet = Number(percentages[key]) >= (threshold[key] || 0); | ||
@@ -196,3 +211,3 @@ if (wasMet) { | ||
const passed = hasPassed(threshold, percentages); | ||
const thresholdSummary = [getThresholdSummaryLine(percentages, 'statements', threshold), getThresholdSummaryLine(percentages, 'branches', threshold), getThresholdSummaryLine(percentages, 'functions', threshold)].filter(x => !!x); // Remove empty strings | ||
const thresholdSummary = [getThresholdSummaryLine(percentages, 'statements', threshold), getThresholdSummaryLine(percentages, 'branches', threshold), getThresholdSummaryLine(percentages, 'functions', threshold), getThresholdSummaryLine(percentages, 'lines', threshold)].filter(x => !!x); // Remove empty strings | ||
@@ -211,5 +226,3 @@ if (passed) { | ||
const getCombinedMetrics = files => files.reduce((acc, file) => { | ||
var _file$metrics; | ||
const fileMetrics = ((_file$metrics = file.metrics) === null || _file$metrics === void 0 ? void 0 : _file$metrics[0].$) || {}; | ||
const fileMetrics = getFileMetrics(file); | ||
Object.keys(fileMetrics).forEach(key => { | ||
@@ -251,3 +264,4 @@ acc[key] = acc[key] || 0 + Number(fileMetrics[key]); | ||
branches: 80, | ||
functions: 80 | ||
functions: 80, | ||
lines: 80 | ||
} | ||
@@ -263,3 +277,3 @@ } = {}) => { | ||
const combinedMetrics = getCombinedMetrics(relevantFiles); | ||
const table = buildTable(relevantFiles, maxRows, threshold); | ||
const table = buildTable(relevantFiles, maxRows, threshold, showAllFiles); | ||
const summary = buildSummary(combinedMetrics, successMessage, failureMessage, threshold); | ||
@@ -266,0 +280,0 @@ const report = ['## Coverage Report', summary, table].join(newLine + newLine); |
{ | ||
"name": "danger-plugin-coverage", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "A Danger plugin to report code coverage.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -30,15 +30,27 @@ # danger-plugin-coverage | ||
``` | ||
Coverage threshold for branches (80%) not met: 33.33% | ||
Coverage threshold for functions (80%) not met: 66.67% | ||
Coverage threshold for branches (80%) not met: 49.08% | ||
Coverage threshold for functions (80%) not met: 74.46% | ||
``` | ||
|Impacted Files|% Stmts|% Branch|% Funcs|| | ||
|---|:-:|:-:|:-:|:-:| | ||
|[src/module-one.js]()|100|100|100|:white_check_mark:| | ||
|[src/module-two.js]()|95.24|33.33|66.67|:x:| | ||
|[src/module-three.js]()|82.33|100|44.55|:x:| | ||
|[src/module-four.js]()|95.24|82.55|81.55|:white_check_mark:| | ||
|Impacted Files|% Stmts|% Branch|% Funcs|% Line|| | ||
|---|:-:|:-:|:-:|:-:|:-:| | ||
|[src/module-one.js]()|100|100|100|100|:white_check_mark:| | ||
|[src/module-two.js]()|95.24|33.33|66.67|100|:x:| | ||
|[src/module-three.js]()|82.33|10.25|44.55|100|:x:| | ||
|[src/module-four.js]()|100|0|10|100|:x:| | ||
|[src/module-five.js]()|100|100|100|100|:white_check_mark:| | ||
<details> | ||
<summary> | ||
and 2 more... | ||
</summary> | ||
|Impacted Files|% Stmts|% Branch|% Funcs|% Lines|| | ||
|---|:-:|:-:|:-:|:-:|:-:| | ||
|[src/module-six.js]()|100|100|100|100|:white_check_mark:| | ||
|[src/module-seven.js]()|100|100|100|100|:white_check_mark:| | ||
</details> | ||
</details> | ||
## Usage | ||
@@ -91,4 +103,5 @@ | ||
functions: 80, | ||
lines: 80, | ||
}, | ||
})); | ||
``` |
@@ -47,2 +47,4 @@ import path from 'path'; | ||
coveredmethods, | ||
lines, | ||
coveredlines, | ||
}) => ({ | ||
@@ -52,5 +54,22 @@ statements: getCoveredPercentage(coveredstatements, statements), | ||
functions: getCoveredPercentage(coveredmethods, methods), | ||
lines: getCoveredPercentage(coveredlines, lines), | ||
}); | ||
/** | ||
* Get the metrics for a file. | ||
*/ | ||
const getFileMetrics = (file) => { | ||
const { line: lines = [], metrics } = file; | ||
const fileMetrics = (metrics?.[0].$ || {}); | ||
const uncoveredLines = lines.filter((line) => !Number(line.$?.count || 0)); | ||
return { | ||
...fileMetrics, | ||
lines: lines.length, | ||
coveredlines: lines.length - uncoveredLines.length, | ||
}; | ||
}; | ||
/** | ||
* Shorten a path so that it fits in a GitHub comment. | ||
@@ -91,2 +110,3 @@ */ | ||
functions, | ||
lines, | ||
}) => ( | ||
@@ -96,2 +116,3 @@ (Number(statements) >= threshold.statements || statements === '-') | ||
&& (Number(functions) >= threshold.functions || functions === '-') | ||
&& (Number(lines) >= threshold.lines || lines === '-') | ||
); | ||
@@ -103,7 +124,4 @@ | ||
const buildRow = (file, threshold) => { | ||
const { line = [], metrics } = file; | ||
const fileMetrics = (metrics?.[0].$ || {}); | ||
const fileMetrics = getFileMetrics(file); | ||
const noLines = !line.length; | ||
const { sha } = danger.git?.commits?.[danger.git.commits.length - 1] || {}; | ||
@@ -116,4 +134,4 @@ const filePath = path.relative(process.cwd(), file.$.path); | ||
const percentages = getMetricPercentages(fileMetrics); | ||
const { statements, branches, functions } = percentages; | ||
const noLines = !fileMetrics.lines; | ||
let emoji = hasPassed(threshold, percentages) ? ':white_check_mark:' : ':x:'; | ||
@@ -128,5 +146,6 @@ | ||
fileCell, | ||
noLines ? '-' : statements, | ||
noLines ? '-' : branches, | ||
noLines ? '-' : functions, | ||
noLines ? '-' : percentages.statements, | ||
noLines ? '-' : percentages.branches, | ||
noLines ? '-' : percentages.functions, | ||
noLines ? '-' : percentages.lines, | ||
emoji, | ||
@@ -145,8 +164,9 @@ '', | ||
*/ | ||
const buildTable = (files, maxRows, threshold) => { | ||
const buildTable = (files, maxRows, threshold, showAllFiles) => { | ||
const headings = [ | ||
'Impacted Files', | ||
`${showAllFiles ? '' : 'Impacted '}Files`, | ||
'% Stmts', | ||
'% Branch', | ||
'% Funcs', | ||
'% Lines', | ||
'', | ||
@@ -156,3 +176,2 @@ ]; | ||
const headingRow = joinRow(headings); | ||
const emptyHeadingRow = joinRow(new Array(headings.length).fill(' ')); | ||
const seperator = joinRow( | ||
@@ -183,3 +202,3 @@ new Array(headings.length).fill().reduce((acc, _, index) => [ | ||
'', | ||
emptyHeadingRow, | ||
headingRow, | ||
seperator, | ||
@@ -198,3 +217,3 @@ ...extraFileRows, | ||
const getThresholdSummaryLine = (percentages, key, threshold) => { | ||
const wasMet = Number(percentages[key]) >= threshold[key]; | ||
const wasMet = Number(percentages[key]) >= (threshold[key] || 0); | ||
@@ -219,2 +238,3 @@ if (wasMet) { | ||
getThresholdSummaryLine(percentages, 'functions', threshold), | ||
getThresholdSummaryLine(percentages, 'lines', threshold), | ||
].filter((x) => !!x); // Remove empty strings | ||
@@ -241,3 +261,3 @@ | ||
const getCombinedMetrics = (files) => files.reduce((acc, file) => { | ||
const fileMetrics = (file.metrics?.[0].$ || {}); | ||
const fileMetrics = getFileMetrics(file); | ||
@@ -282,2 +302,3 @@ Object.keys(fileMetrics).forEach((key) => { | ||
functions: 80, | ||
lines: 80, | ||
}, | ||
@@ -294,3 +315,3 @@ } = {}) => { | ||
const combinedMetrics = getCombinedMetrics(relevantFiles); | ||
const table = buildTable(relevantFiles, maxRows, threshold); | ||
const table = buildTable(relevantFiles, maxRows, threshold, showAllFiles); | ||
const summary = buildSummary(combinedMetrics, successMessage, failureMessage, threshold); | ||
@@ -297,0 +318,0 @@ const report = [ |
@@ -64,3 +64,3 @@ import path from 'path'; | ||
expect(lines).toContain(successMessage); | ||
expect(lines).toContain('|src/one.js|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|src/one.js|100|100|100|100|:white_check_mark:|'); | ||
}); | ||
@@ -86,2 +86,3 @@ | ||
metric === 'methods' ? '0' : '100', | ||
'100', // lines tested separately | ||
':x:', | ||
@@ -113,2 +114,34 @@ '', | ||
it('reports row as failing when lines does not meet the threshold', async () => { | ||
const file = getFileXml('src/one.js', defautMetrics, [ | ||
{ | ||
num: 1, | ||
count: 0, | ||
type: 'stmt', | ||
}, | ||
]); | ||
const xmlReport = wrapXmlReport(file); | ||
mockFs({ | ||
[cloverPath]: xmlReport, | ||
}); | ||
Object.assign(danger, { | ||
git: { | ||
created_files: ['src/one.js'], | ||
modified_files: [], | ||
}, | ||
}); | ||
await coverage(); | ||
const report = getMarkdownReport(); | ||
const lines = report.split('\n'); | ||
expect(report).toMatchSnapshot(); | ||
expect(lines).toContain(failureMessage); | ||
expect(lines).toContain('Coverage threshold for lines (80%) not met: 0%'); | ||
expect(lines).toContain('|src/one.js|100|100|100|0|:x:|'); | ||
}); | ||
it.each(['project', 'package'])('handles multiple %ss', async (parentElement) => { | ||
@@ -153,5 +186,5 @@ const fileOne = getFileXml('src/one.js', defautMetrics, [defaultLine]); | ||
expect(lines).toContain(successMessage); | ||
expect(lines).toContain('|src/one.js|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|src/two.js|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|src/three.js|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|src/one.js|100|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|src/two.js|100|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|src/three.js|100|100|100|100|:white_check_mark:|'); | ||
}); | ||
@@ -187,3 +220,3 @@ | ||
expect(lines).toContain(successMessage); | ||
expect(lines).not.toContain('|src/three.js|100|100|100|:white_check_mark:|'); | ||
expect(lines).not.toContain('|src/three.js|100|100|100|100|:white_check_mark:|'); | ||
}); | ||
@@ -246,3 +279,3 @@ | ||
expect(lines).toContain(successMessage); | ||
expect(lines).toContain('|src/one.js|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|src/one.js|100|100|100|100|:white_check_mark:|'); | ||
}); | ||
@@ -280,3 +313,3 @@ | ||
expect(lines).toContain(successMessage); | ||
expect(lines).toContain('|src/one.js|-|-|-|-|'); | ||
expect(lines).toContain('|src/one.js|-|-|-|-|-|'); | ||
}); | ||
@@ -310,3 +343,3 @@ | ||
expect(lines).toContain( | ||
`|../${seg}/${seg}/${seg}/${seg}/${seg}|100|100|100|:white_check_mark:|`, | ||
`|../${seg}/${seg}/${seg}/${seg}/${seg}|100|100|100|100|:white_check_mark:|`, | ||
); | ||
@@ -347,3 +380,3 @@ }); | ||
expect(lines).toContain('Coverage threshold for functions (80%) not met: 66.67%'); | ||
expect(lines).toContain('|src/one.js|95.24|33.33|66.67|:x:|'); | ||
expect(lines).toContain('|src/one.js|95.24|33.33|66.67|100|:x:|'); | ||
}); | ||
@@ -378,5 +411,5 @@ | ||
expect(report).toMatchSnapshot(); | ||
expect(lines).toContain('|[src/one.js](../blob/abc123/src/one.js)|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|[src/two.js](../blob/abc123/src/two.js)|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|[src/one.js](../blob/abc123/src/one.js)|100|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|[src/two.js](../blob/abc123/src/two.js)|100|100|100|100|:white_check_mark:|'); | ||
}); | ||
}); |
@@ -115,3 +115,3 @@ import path from 'path'; | ||
expect(lines).toContain('|from-custom-report.js|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|from-custom-report.js|100|100|100|100|:white_check_mark:|'); | ||
}); | ||
@@ -163,3 +163,4 @@ | ||
expect(lines).toContain('|src/one.js|100|100|100|:white_check_mark:|'); | ||
expect(lines).toContain('|Files|% Stmts|% Branch|% Funcs|% Lines||'); | ||
expect(lines).toContain('|src/one.js|100|100|100|100|:white_check_mark:|'); | ||
}); | ||
@@ -175,3 +176,14 @@ | ||
coveredmethods: 9, | ||
}, [defaultLine]); | ||
}, [ | ||
{ | ||
num: 1, | ||
count: 0, | ||
type: 'stmt', | ||
}, | ||
{ | ||
num: 1, | ||
count: 1, | ||
type: 'stmt', | ||
}, | ||
]); | ||
const xmlReport = wrapXmlReport(file); | ||
@@ -196,2 +208,3 @@ | ||
functions: 100, | ||
lines: 50, | ||
}, | ||
@@ -204,4 +217,4 @@ }); | ||
expect(lines).toContain('> Not good'); | ||
expect(lines).toContain('|src/one.js|90|90|90|:x:|'); | ||
expect(lines).toContain('|src/one.js|90|90|90|50|:x:|'); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
46960
7.62%1131
6.8%106
13.98%