Sourcemap writer for karma-webpack to work with istanbul.
Testing webpack project with karma-webpack is cool, until you want to use istanbul to do code coverage.
The codes were transpiled by webpack loaders so the coverage is not accurate.
Use karma-sourcemap-writer to write source map file into right place and let remap-istanbul remap Istanbul code coverage information to its original source positions.
npm install --save-dev karma-sourcemap-writer
- Setup karma-webpack in the alternative way. Let's call this file
tests.webpack.js
.
const context = require.context('./test', true, /.spec\.js$/);
context.keys().forEach(context);
- Append
sourceMappingURL
totests.webpack.js
.
const context = require.context('./test', true, /.spec\.js$/);
context.keys().forEach(context);
//# sourceMappingURL=tests.webpack.js.map
- Set
devtool
toinline-source-map
webpack: {
// ...
devtool: 'inline-source-map'
}
- Apply
karma-sourcemap-writer
andkarma-coverage
const webpackConfig = require('./webpack/config.test.js');
module.exports = function set(config) {
config.set({
browsers: ['Chrome'],
singleRun: true,
frameworks: ['mocha'],
files: [
'tests.webpack.js'
],
preprocessors: {
'tests.webpack.js': [
'webpack',
'sourcemap',
'sourcemap-writer', // important!
'coverage' // important!
]
},
reporters: [
'mocha',
'coverage' // important!
],
webpack: webpackConfig,
webpackServer: {
noInfo: true
},
coverageReporter: { // important!
type: 'json',
subdir: '.',
file: 'coverage-final.json'
},
plugins: [
'karma-chrome-launcher',
'karma-webpack',
'karma-mocha',
'karma-mocha-reporter',
'karma-sourcemap-loader',
'karma-sourcemap-writer', // important!
'karma-coverage' // important!
]
});
};
- Run karma. This will generate
coverage/coverage-final.json
andtests.webpack.js.map
besidetests.webpack.js
karma start
- Run
remap-istanbul
to generate mapped report
remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped.json -t json
- Generate clean coverage report
At this stage this report contains lots of unrelated coverage information, we have to run a script to remove them. Thanks to @otbe for the solution.
Create a node script and execute it.
const istanbul = require('istanbul');
const collector = new istanbul.Collector();
const reporter = new istanbul.Reporter();
const remappedJson = require('./coverage/coverage-remapped.json');
const coverage = Object.keys(remappedJson).reduce((result, source) => {
// only keep js files under src/
if (source.match(/^src\/.*\.js$/)) {
result[source] = remappedJson[source];
}
return result;
}, {});
collector.add(coverage);
reporter.add('html');
reporter.write(
collector,
true,
() => console.log('open coverage/index.html to see the coverage report.')
);
Done.