Closed stijnvn closed 6 years ago
There is no build-in way to do it.
Having one report doesn't really work for most organizations. Imagine you have two teams building two apps in the same repo. The fact that one team failed to meet a certain threshold shouldn't affect the other team.
So we can have a report per team (app+all its libs), but then the situation tricky if you have a lot of shared libs.
I think the simplest thing to do is to have a threshold per project (app or lib). In this case you can set custom rules depending on your setup (e.g., shared libs' threshold can be higher).
But if you want to have a combined code coverage report? How do you do it?
You can output your coverage via json reporter per lib/app and use something like this script to combine them and build a html report at the end. - That is the approach we took, but have no solution for result combination yet.
Here's a script that demonstrates how I generate the summarized report of all libs in my coverage directory.
const fs = require( 'fs-extra');
const glob = require('glob');
const { createReporter } = require('istanbul-api');
const istanbulCoverage = require('istanbul-lib-coverage');
const reporter = createReporter();
/* [ Configuration ] */
const rootDir = './coverage/libs';
const reportOut = './coverage/report';
const normalizeJestCoverage = ( obj ) => {
const result = { ...obj };
Object
.entries( result )
.filter( ([k, v] ) => v.data )
.forEach( ([k, v] ) => {
result[k] = v.data;
});
return result;
};
const mergeAllReports = ( coverageMap, reports ) => {
if ( Array.isArray( reports ) === false ) {
return;
}
reports.forEach( reportFile => {
const coverageReport = fs.readJSONSync( reportFile );
coverageMap.merge( normalizeJestCoverage( coverageReport ) );
})
};
const findAllCoverageReports = ( path, callback ) => {
glob( path, {}, ( err, reports )=>{
callback( reports, err );
});
};
const generateReport = ( coverageMap, types ) => {
reporter.dir = reportOut;
reporter.addAll(types || ['html', 'text'] );
reporter.write( coverageMap );
};
async function main () {
const coverageMap = istanbulCoverage.createCoverageMap( {} );
findAllCoverageReports( rootDir + '/**/coverage-final.json', ( reports, err ) => {
if ( Array.isArray( reports ) ) {
mergeAllReports( coverageMap, reports );
generateReport( coverageMap, [ 'text' ] )
}
});
}
main().catch(err => {
console.error(err);
process.exit(1);
});
istanbul-combine is the best solution I've found for this. It uses an old version of istanbul internally, but it worked for me.
I've written a short blog post about it with my solution: https://yonatankra.com/how-to-create-a-workspace-coverage-report-in-nrwl-nx-monorepo/ Hope this helps
here is an updated version of @alexus85 code above, using the newer 'istanbul-reports' since 'istanbul-api' is depracated:
const fs = require('fs-extra');
const glob = require('glob');
const istanbulReports = require('istanbul-reports');
const libReport = require('istanbul-lib-report');
const istanbulCoverage = require('istanbul-lib-coverage');
/* [ Configuration ] */
const rootDir = './coverage';
const reportOut = './coverage/report';
const configWatermarks = {
statements: [50, 80],
functions: [50, 80],
branches: [0, 80],
lines: [50, 80],
};
const normalizeJestCoverage = (obj) => {
const result = { ...obj };
Object.entries(result)
.filter(([k, v]) => v.data)
.forEach(([k, v]) => {
result[k] = v.data;
});
return result;
};
const mergeAllReports = (coverageMap, reports) => {
if (Array.isArray(reports) === false) {
return;
}
reports.forEach((reportFile) => {
const coverageReport = fs.readJSONSync(reportFile);
coverageMap.merge(normalizeJestCoverage(coverageReport));
});
};
const findAllCoverageReports = (path, callback) => {
glob(path, {}, (err, reports) => {
callback(reports, err);
});
};
const generateReport = (coverageMap, type) => {
const context = libReport.createContext({
dir: reportOut,
// The summarizer to default to (may be overridden by some reports)
// values can be nested/flat/pkg. Defaults to 'pkg'
defaultSummarizer: 'nested',
watermarks: configWatermarks,
coverageMap,
});
const report = istanbulReports.create(type, {
skipEmpty: false,
skipFull: true, // skip text lines with 100%
verbose: true, // verbose html report
});
report.execute(context);
};
async function main() {
const coverageMap = istanbulCoverage.createCoverageMap({});
findAllCoverageReports(rootDir + '/**/coverage-final.json', (reports, err) => {
if (Array.isArray(reports)) {
mergeAllReports(coverageMap, reports);
generateReport(coverageMap, 'text');
generateReport(coverageMap, 'html');
}
});
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.
How do you generate a combined code coverage report with Nx 6?