I have started a project by using the Angular ASP.NET Core 2.0 template as found in Visual Studio 2017 Update 3 after installing the .NET Core 2.0 SDK.
Tests in Karma work fine, but I want to add code coverage to Karma. I have tried several different solutions, but nothing seems to work fully. The best I have come up with is that classes referenced from tests are covered (but not all typescript classes in the ClientApp), but the highlighting in the generated report is off and the messages don't make sense.
This is what I have done:
package.json
"devDependencies": {
"@types/chai": "4.0.1",
"@types/jasmine": "2.5.53",
"chai": "4.0.2",
"istanbul-instrumenter-loader": "^3.0.0",
"jasmine-core": "2.6.4",
"karma": "https://registry.npmjs.org/karma/-/karma-1.7.0.tgz",
"karma-chai": "0.1.0",
"karma-chrome-launcher": "2.2.0",
"karma-cli": "1.0.1",
"karma-coverage": "^1.1.1",
"karma-jasmine": "1.1.0",
"karma-remap-istanbul": "https://registry.npmjs.org/karma-remap-istanbul/-/karma-remap-istanbul-0.6.0.tgz",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "2.0.3"
}
Karma.conf.js:
module.exports = function (config) {
var webpackConfig = require('../../webpack.config.js')().filter(config => config.target !== 'node');
webpackConfig[0].devtool = 'inline-source-map';
config.set({
basePath: '.',
frameworks: ['jasmine'],
files: [
'../../wwwroot/dist/vendor.js',
'./boot-tests.ts'
],
preprocessors: {
'./boot-tests.ts': ['webpack', 'sourcemap']
},
reporters: ['progress', 'coverage', 'karma-remap-istanbul'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
mime: { 'application/javascript': ['ts','tsx'] },
singleRun: false,
webpack: webpackConfig, // Test against client bundle, because tests run in a browser
webpackMiddleware: { stats: 'errors-only' },
remapIstanbulReporter: {
reports: {
html: 'coverage'
}
}
});
};
webpack.config.js:
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const AotPlugin = require('@ngtools/webpack').AotPlugin;
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
module.exports = (env) => {
// Configuration in common to both client-side and server-side bundles
const isDevBuild = !(env && env.prod);
const tsUse = isDevBuild ? [
{
loader: 'istanbul-instrumenter-loader',
options: {
esModules: true
}
},
'awesome-typescript-loader?silent=true',
'angular2-template-loader'
] : '@ngtools/webpack';
const sharedConfig = {
stats: { modules: false },
context: __dirname,
resolve: { extensions: ['.js', '.ts'] },
output: {
filename: '[name].js',
publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [
{
test: /\.ts$/, include: /ClientApp/,
use: tsUse
},
{ test: /\.html$/, use: 'html-loader?minimize=false' },
{
test: /\.css$/, use: ['to-string-loader', isDevBuild ? 'css-loader' : 'css-loader?minimize']
},
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
]
},
plugins: [new CheckerPlugin()]
};
// Configuration for client-side bundle suitable for running in browsers
const clientBundleOutputDir = './wwwroot/dist';
const clientBundleConfig = merge(sharedConfig, {
entry: { 'main-client': './ClientApp/boot.browser.ts' },
output: { path: path.join(__dirname, clientBundleOutputDir) },
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
})
].concat(isDevBuild ? [
// Plugins that apply in development builds only
new webpack.SourceMapDevToolPlugin({
filename: '[file].map', // Remove this line if you prefer inline source maps
moduleFilenameTemplate: path.relative(clientBundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
})
] : [
// Plugins that apply in production builds only
new webpack.optimize.UglifyJsPlugin(),
new AotPlugin({
tsConfigPath: './tsconfig.json',
entryModule: path.join(__dirname, 'ClientApp/app/app.module.browser#AppModule'),
exclude: ['./**/*.server.ts']
})
])
});
// Configuration for server-side (prerendering) bundle suitable for running in Node
const serverBundleConfig = merge(sharedConfig, {
resolve: { mainFields: ['main'] },
entry: { 'main-server': './ClientApp/boot.server.ts' },
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./ClientApp/dist/vendor-manifest.json'),
sourceType: 'commonjs2',
name: './vendor'
})
].concat(isDevBuild ? [] : [
// Plugins that apply in production builds only
new AotPlugin({
tsConfigPath: './tsconfig.json',
entryModule: path.join(__dirname, 'ClientApp/app/app.module.server#AppModule'),
exclude: ['./**/*.browser.ts']
})
]),
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, './ClientApp/dist')
},
target: 'node',
devtool: 'inline-source-map'
});
return [clientBundleConfig, serverBundleConfig];
};