Setting up unit test code coverage on Angular 2.1.0 Webpack - unit-testing
I am Following this tutorial on setting up a Webpack Angular 2 project.
I can run unit tests just fine with the setup, but I have tried adding code coverage to the project using karma-coverage and remap-istanbul, but it seems that karma-coverage is not outputting anything in the coverage-final.json.
What do I need to add to the karma config to get the test config to work?
Here is my current config:
var webpackConfig = require('./webpack.test');
module.exports = function (config) {
var _config = {
basePath: '',
frameworks: ['jasmine'],
files: [
{pattern: './config/karma-test-shim.js', watched: false}
],
preprocessors: {
'./config/karma-test-shim.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
stats: 'errors-only'
},
webpackServer: {
noInfo: true
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['PhantomJS'],
singleRun: true
};
config.set(_config);
};
You have two options, the easiest way is to use angular-cli. The hardest way is based on that tutorial make the changes needed for code coverage, which are a lot. One of the main things that you will be forced is to change to Webpack 2, I wasn't able to make awesome-typescript-loader work with karma using Webpack 1. The code coverage was always empty. I got some inspiration from angular-cli and from angular2-webpack-starter here are the changes:
karma.conf.js: add this:
remapIstanbulReporter: {
reports: {
html: 'coverage',
lcovonly: './coverage/coverage.lcov'
}
},
And change this:
reporters: ['progress'],
to this:
reporters: ['progress', 'karma-remap-istanbul'],
There are a lot of changes to the webpack configs so I'm just going to paste the entire config files, it's easier:
webpack.common.js:
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
module.exports = {
entry: {
'polyfills': './src/polyfills.ts',
'vendor': './src/vendor.ts',
'app': './src/main.ts'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader'],
exclude: [/\.(spec|e2e)\.ts$/]
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style-loader',
loader: 'css-loader'
})
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw'
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
// Optimizing ensures loading order in index.html
name: ['polyfills', 'vendor', 'app'].reverse()
}),
new webpack.optimize.CommonsChunkPlugin({
minChunks: Infinity,
name: 'inline',
filename: 'inline.js',
sourceMapFilename: 'inline.map'
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
};
webpack.dev.js
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');
module.exports = webpackMerge(commonConfig, {
devtool: 'cheap-module-eval-source-map',
output: {
path: helpers.root('dist'),
filename: '[name].js',
chunkFilename: '[id].chunk.js',
sourceMapFilename: '[name].map',
library: 'ac_[name]',
libraryTarget: 'var'
},
plugins: [
new webpack.LoaderOptionsPlugin({
options: {
tslint: {
emitErrors: false,
failOnHint: false,
resourcePath: 'src'
},
}
}),
new ExtractTextPlugin('[name].css')
],
devServer: {
historyApiFallback: true,
stats: 'minimal',
watchOptions: {
aggregateTimeout: 300,
poll: 1000
},
outputPath: helpers.root('dist')
},
node: {
global: true,
crypto: 'empty',
process: true,
module: false,
clearImmediate: false,
setImmediate: false
}
});
webpack.prod.js:
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var WebpackMd5Hash = require('webpack-md5-hash');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
module.exports = webpackMerge(commonConfig, {
devtool: 'source-map',
output: {
path: helpers.root('dist'),
filename: '[name].[chunkhash].js',
sourceMapFilename: '[name].[chunkhash].bundle.map',
chunkFilename: '[id].[chunkhash].chunk.js'
},
plugins: [
new WebpackMd5Hash(),
new webpack.NoErrorsPlugin(),
new webpack.optimize.UglifyJsPlugin({
mangle: { screw_ie8: true },
compress: { screw_ie8: true }
}),
new ExtractTextPlugin('[name].[hash].css'),
new webpack.DefinePlugin({
'process.env': {
'ENV': JSON.stringify(ENV)
}
}),
new webpack.LoaderOptionsPlugin({
options: {
tslint: {
emitErrors: true,
failOnHint: true,
resourcePath: helpers.root('src')
},
htmlLoader: {
minimize: true,
removeAttributeQuotes: false,
caseSensitive: true,
customAttrSurround: [
[/#/, /(?:)/],
[/\*/, /(?:)/],
[/\[?\(?/, /(?:)/]
],
customAttrAssign: [/\)?\]?=/]
}
}
}),
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
helpers.root('src')
)
],
node: {
fs: 'empty',
global: true,
crypto: 'empty',
process: true,
module: false,
clearImmediate: false,
setImmediate: false
}
});
webpack.test.js:
var helpers = require('./helpers');
var path = require('path');
var atl = require('awesome-typescript-loader');
var webpack = require('webpack');
module.exports = {
devtool: 'inline-source-map',
context: path.resolve(__dirname, './'),
resolve: {
extensions: ['.ts', '.js'],
plugins: [
new atl.TsConfigPathsPlugin({
tsconfig: helpers.root('tsconfig.json')
})
]
},
entry: {
test: helpers.root('config/karma-test-shim')
},
output: {
path: './dist.test',
filename: '[name].bundle.js'
},
module: {
rules: [
{
test: /\.ts$/,
enforce: 'pre',
loader: 'tslint-loader',
exclude: [
helpers.root('node_modules')
]
},
{
test: /\.js$/,
enforce: 'pre',
loader: 'source-map-loader',
exclude: [
helpers.root('node_modules/rxjs'),
helpers.root('node_modules/#angular')
]
},
{
test: /\.ts$/,
loaders: [
{
loader: 'awesome-typescript-loader',
query: {
tsconfig: helpers.root('tsconfig.json'),
module: 'commonjs',
target: 'es5',
useForkChecker: true
}
},
{
loader: 'angular2-template-loader'
}
],
exclude: [/\.e2e\.ts$/]
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'null'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: 'null'
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw'
},
{
test: /\.(js|ts)$/, loader: 'sourcemap-istanbul-instrumenter-loader',
enforce: 'post',
exclude: [
/\.(e2e|spec)\.ts$/,
/node_modules/
],
query: { 'force-sourcemap': true }
},
]
},
plugins: [
new webpack.SourceMapDevToolPlugin({
filename: null, // if no value is provided the sourcemap is inlined
test: /\.(ts|js)($|\?)/i // process .js and .ts files only
}),
new webpack.LoaderOptionsPlugin({
options: {
tslint: {
emitErrors: false,
failOnHint: false,
resourcePath: `./src`
}
}
}),
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
helpers.root('src')
)
],
node: {
fs: 'empty',
global: true,
process: false,
crypto: 'empty',
module: false,
clearImmediate: false,
setImmediate: false
}
}
package.json:
You will need to install new packages and update your start script to this:
"start": "webpack-dev-server --config config/webpack.dev.js --profile --watch --content-base src/",
And install these packages:
npm i -D extract-text-webpack-plugin#2.0.0-beta.4 karma-remap-istanbul source-map-loader sourcemap-istanbul-instrumenter-loader tslint tslint-loader webpack#2.1.0-beta.25 webpack-dev-server#2.1.0-beta.3 webpack-md5-hash
Last but not least we just need to do some changes on the tsconfig.json and since we are now using tslint we add the a tslint.json file.
tsconfig.json:
{
"compilerOptions": {
"buildOnSave": false,
"compileOnSave": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"module": "commonjs",
"moduleResolution": "node",
"outDir": "dist/out-tsc",
"noImplicitAny": true,
"removeComments": false,
"sourceMap": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es5"
}
}
tslint.json:
{
"rules": {
"member-access": false,
"member-ordering": [
true,
"public-before-private",
"static-before-instance",
"variables-before-functions"
],
"no-any": false,
"no-inferrable-types": false,
"no-internal-module": true,
"no-var-requires": false,
"typedef": false,
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
},
{
"call-signature": "space",
"index-signature": "space",
"parameter": "space",
"property-declaration": "space",
"variable-declaration": "space"
}
],
"ban": false,
"curly": false,
"forin": true,
"label-position": true,
"label-undefined": true,
"no-arg": true,
"no-bitwise": true,
"no-conditional-assignment": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-variable": true,
"no-empty": false,
"no-eval": true,
"no-null-keyword": false,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-switch-case-fall-through": true,
"no-unreachable": true,
"no-unused-expression": true,
"no-unused-variable": false,
"no-use-before-declare": true,
"no-var-keyword": true,
"radix": true,
"switch-default": true,
"triple-equals": [
true,
"allow-null-check"
],
"use-strict": [
true,
"check-module"
],
"eofline": true,
"indent": [
true,
"spaces"
],
"max-line-length": [
true,
100
],
"no-require-imports": false,
"no-trailing-whitespace": true,
"object-literal-sort-keys": false,
"trailing-comma": [
true,
{
"multiline": false,
"singleline": "never"
}
],
"align": false,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"interface-name": false,
"jsdoc-format": true,
"no-consecutive-blank-lines": false,
"no-constructor-vars": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-finally",
"check-whitespace"
],
"quotemark": [
true,
"single",
"avoid-escape"
],
"semicolon": [true, "always"],
"variable-name": [
true,
"check-format",
"allow-leading-underscore",
"ban-keywords"
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}
If you want you can check the differences between the Angular.io setup (on the left) and the changes I made to make coverage work (on the right) here
Related
Webpack 5 Module Federation + splitchunks.chunks "all" error
I've been working on using ModuleFederation and have ran into an issue where if the remote webpack configuration had optimize.splitChunks.chunk = "all" then the host application would throw a loadScript exception. This could be a complete fundamental knowledge gap on my part why that wouldn't work. I haven't seen any documentation on not using that option along with Module Federation. Has anyone had similar experiences or can tell me why it's a conflicting setting? Thanks for your help! remote webpack.config.js const path = require("path"); const webpack = require("webpack"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const { ModuleFederationPlugin } = webpack.container; module.exports = { entry: "./index.js", mode: "development", devServer: { contentBase: path.join(__dirname, "dist"), port: 1338, }, output: { publicPath: "auto", }, optimization: { splitChunks: { chunk: "all" } }, module: { rules: [ { test: /\.jsx?$/, loader: "babel-loader", exclude: /node_modules/, options: { presets: ["#babel/preset-react"], }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: "comic", filename: "remoteEntry.js", exposes: { "./XKCD": "./app.jsx", }, shared: [ { react: { singleton: true, eager: true }, "react-dom": { singleton: true, eager: true }, }, ], }), new HtmlWebpackPlugin({ template: "./index.html", }), ], }; host webpack.config.js const HtmlWebpackPlugin = require("html-webpack-plugin"); const ModuleFederationPlugin = require("webpack").container .ModuleFederationPlugin; const path = require("path"); module.exports = { entry: "./index.js", mode: "development", devServer: { contentBase: path.join(__dirname, "dist"), port: 1337, }, output: { publicPath: "auto", }, module: { rules: [ { test: /\.jsx?$/, loader: "babel-loader", exclude: /node_modules/, options: { presets: ["#babel/preset-react"], }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: "home", filename: "remoteEntry.js", remotes: { comic: `comic#http://localhost:1338/remoteEntry.js)`, }, shared: [ { react: { singleton: true, eager: true }, "react-dom": { singleton: true, eager: true }, }, ], }), new HtmlWebpackPlugin({ template: "./index.html", }), ], };
I have a similar problem. I change the remote webpack.config.js optimization.splitChunks as optimization: { splitChunks: { chunks: 'async' } } This problem is fixed. Maybe you can try it. Sorry my pool english
Webpack multiple chunks include same dependency
I want to have some dependencies in different chunks so client.js would be smaller. webpack 4.16.5 Why I get same code included to several chunks? What's missing? const path = require('path'); const webpack = require('webpack'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { mode: 'production', target: 'web', // devtool: 'source-map', entry: { echarts: ['echarts'], vendor_1: ['react', 'immutable', 'lodash', 'redux', 'redux-saga'], vendor_2: ['#material-ui/core', '#tinymce/tinymce-react'], client: ['babel-polyfill', path.join(__dirname, 'app/index.js')], }, output: { path: path.join(__dirname, '/dist/'), filename: '[hash].[name].js', publicPath: './', }, resolve: { modules: [ path.join(__dirname, '/app'), 'node_modules', ], }, plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ template: 'app/index.tpl.html', inject: 'body', filename: 'index.html', }), new BundleAnalyzerPlugin(), ], module: { rules: [ { test: /\.js?$/, exclude: /node_modules/, use: [{ loader: 'babel-loader', }], }, { test: /\.scss$/, use: [ 'style-loader', 'css-loader?modules&localIdentName=[name]---[local]---[hash:base64:5]', 'sass-loader', ], }, { test: /\.woff(2)?(\?[a-z0-9#=&.]+)?$/, use: [{ loader: 'url?limit=10000&mimetype=application/font-woff', }], }, { test: /\.(ttf|eot|svg)(\?[a-z0-9#=&.]+)?$/, use: [{ loader: 'file', }], }, ], }, };
I added optimization config and it works now as expected. optimization: { splitChunks: { chunks: 'initial', }, }, I've played with values a bit and this was the best result for my code base without any extra code edits. You can find all possible options here: https://webpack.js.org/configuration/optimization/ Thanks Pavel for the tip ;)
Unable to generate code coverage report for all ts files using Karma, Webpack, remap coverage
I am able to set up Unit test framework using Karma, Webpack and karma-remap-coverage for code coverage. But I don't understand why coverage is not coming for all the files(components, directives, services). I have around, supposed 100 files, but it's generating coverage report only for 40-50 files. Here I am sharing my configuration files: Karma.conf.js var webpackConfig = require('./webpack/webpack.test'); var path = require('path'); module.exports = function (config) { var _config = { basePath: '', frameworks: ['jasmine'], files: [ { pattern: './webpack/karma-test-shim.js', watched: false }, { pattern: './node_modules/#angular/material/prebuilt-themes/indigo-pink.css', included: true, watched: false } ], preprocessors: { './webpack/karma-test-shim.js': ['webpack', 'sourcemap'], }, webpack: webpackConfig, webpackMiddleware: { stats: 'errors-only' }, webpackServer: { noInfo: true }, coverageReporter: { includeAllSources: true, type: 'html', dir: 'coverage/' }, // coverageIstanbulReporter: { // reports: ['html', 'lcovonly'], // fixWebpackSourcePaths: true // }, // reporters: ['progress', 'coverage-istanbul'], coverageReporter: { type: 'in-memory' }, remapCoverageReporter: { 'text-summary': null, json: './coverage/coverage.json', html: './coverage/html', cobertura: './coverage/cobertura.xml' }, reporters: ['progress', 'coverage', 'remap-coverage'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: false, browsers: ['Chrome'], singleRun: true, browserNoActivityTimeout: 20000 }; config.set(_config); }; Webpack.test.js var webpack = require('webpack'); var helpers = require('./helpers'); var path = require('path'); module.exports = { devtool: 'inline-source-map', resolve: { extensions: ['.ts', '.js'] }, module: { rules: [ { test: /\.ts$/, loaders: [ { loader: 'awesome-typescript-loader?sourceMap=false,inlineSourceMap=true', options: { configFileName: 'tsconfig.json' } }, 'angular2-template-loader' ] }, { test: /\.html$/, loader: 'html-loader' }, { test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, loader: 'null-loader' }, { test: /\.css$/, exclude: helpers.root('app'), loader: 'null-loader' }, { test: /\.css$/, include: helpers.root('app'), loader: 'raw-loader' }, { enforce: 'post', test: /\.ts$/, loader: 'istanbul-instrumenter-loader', include: helpers.root('app'), exclude: /(node_modules|\.spec\.ts)/ } ] } } Karma-test-shim.js Error.stackTraceLimit = Infinity; require('core-js/es6'); require('core-js/es7/reflect'); require('zone.js/dist/zone'); require('zone.js/dist/long-stack-trace-zone'); require('zone.js/dist/proxy'); require('zone.js/dist/sync-test'); require('zone.js/dist/jasmine-patch'); require('zone.js/dist/async-test'); require('zone.js/dist/fake-async-test'); var appContext = require.context('../testing/specs', true, /\.spec\.ts/); appContext.keys().forEach(appContext); var testing = require('#angular/core/testing'); var browser = require('#angular/platform-browser-dynamic/testing'); testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting()); NPM dependencies used: "karma": "^1.2.0", "karma-chrome-launcher": "^2.0.0", "karma-cli": "~1.0.1", "karma-coverage": "^1.1.1", "istanbul-instrumenter-loader": "2.0.0", "karma-html-reporter": "^0.2.7", "karma-jasmine": "^1.0.2", "karma-jasmine-html-reporter": "^0.2.2", "karma-mocha-reporter": "^2.2.3", "karma-remap-coverage": "^0.1.2", "karma-sourcemap-loader": "^0.3.7", "karma-webpack": "^2.0.1", Any help is really appreciated!
3rd Party library testing angular 2 webpack
I am working on a project using angular 2 and a 3rd party library for making charts (AmCharts). I figured out how to use it along angular 2, but I'm getting a error when I try to make a unit test for the chart component: Error: Error in ./ChartsComponent class ChartsComponent - inline template:1:2 caused by: AmCharts is not defined ReferenceError: AmCharts is not defined This project has been created using angular-cli and we've recently upgraded angular to version 2.2.1. Here is angular-cli.json and karma.conf.js: angular-cli.json { "project": { "version": "1.0.0-beta.21", "name": "cli-crud-webpack" }, "apps": [ { "root": "src", "outDir": "dist", "assets": [ "assets", "favicon.ico" ], "index": "index.html", "main": "main.ts", "test": "test.ts", "tsconfig": "tsconfig.json", "prefix": "gov", "mobile": false, "styles": [ "styles.scss", "../public/assets/css/agate.css", "../public/assets/css/bootstrap.min.css" ], "scripts": [ "../public/assets/js/highlight.pack.js", "../node_modules/amcharts3/amcharts/amcharts.js", "../node_modules/amcharts3/amcharts/xy.js", "../node_modules/amcharts3/amcharts/gauge.js", "../node_modules/amcharts3/amcharts/serial.js", "../node_modules/amcharts3/amcharts/pie.js", "../node_modules/amcharts3/amcharts/themes/light.js", "../node_modules/amcharts3/amcharts/themes/dark.js", "../node_modules/amcharts3/amcharts/themes/black.js", "../node_modules/amcharts3/amcharts/plugins/responsive/responsive.min.js" ], "environments": { "source": "environments/environment.ts", "dev": "environments/environment.ts", "prod": "environments/environment.prod.ts" } } ], "addons": [], "packages": [], "e2e": { "protractor": { "config": "./protractor.conf.js" } }, "test": { "karma": { "config": "./karma.conf.js" } }, "defaults": { "styleExt": "scss", "prefixInterfaces": false, "inline": { "style": false, "template": false }, "spec": { "class": false, "component": true, "directive": true, "module": false, "pipe": true, "service": true } } } karma.conf.js module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', 'angular-cli'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-remap-istanbul'), require('angular-cli/plugins/karma') ], files: [ { pattern: './src/test.ts', watched: false } ], preprocessors: { './src/test.ts': ['angular-cli'] }, mime: { 'text/x-typescript': ['ts','tsx'] }, remapIstanbulReporter: { reports: { html: 'coverage', lcovonly: './coverage/coverage.lcov' } }, angularCli: { config: './angular-cli.json', environment: 'dev' }, reporters: config.angularCli && config.angularCli.codeCoverage ? ['progress', 'karma-remap-istanbul'] : ['progress'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false }); };
I just found out I have to declare amcharts in karma configuration file, like this: module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', 'angular-cli'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-remap-istanbul'), require('angular-cli/plugins/karma') ], files: [ { pattern: './src/test.ts', watched: false }, "./public/assets/js/highlight.pack.js", "./node_modules/amcharts3/amcharts/amcharts.js", "./node_modules/amcharts3/amcharts/xy.js", "./node_modules/amcharts3/amcharts/gauge.js", "./node_modules/amcharts3/amcharts/serial.js", "./node_modules/amcharts3/amcharts/pie.js", "./node_modules/amcharts3/amcharts/themes/light.js", "./node_modules/amcharts3/amcharts/themes/dark.js", "./node_modules/amcharts3/amcharts/themes/black.js", "./node_modules/amcharts3/amcharts/plugins/responsive/responsive.min.js" ], preprocessors: { './src/test.ts': ['angular-cli'] }, mime: { 'text/x-typescript': ['ts','tsx'] }, remapIstanbulReporter: { reports: { html: 'coverage', lcovonly: './coverage/coverage.lcov' } }, angularCli: { config: './angular-cli.json', environment: 'dev' }, reporters: config.angularCli && config.angularCli.codeCoverage ? ['progress', 'karma-remap-istanbul'] : ['progress'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false }); };
configure coverage for karma webpack with angular 2
How do I set up karma-coverage with angular2 + webpack? I followed the quickstart webpack guide from angular. But the coverage tool is blank and does not display my tests. Thanks! my folder structure is project |--src (project files) |--tests (all my testfiles) my webpack.test.js looks like this var helpers = require('./helpers'); module.exports = { devtool: 'inline-source-map', resolve: { extensions: ['', '.ts', '.js'] }, module: { loaders: [ { test: /\.ts$/, loaders: ['ts'] }, { test: /\.html$/, loader: 'null' }, { test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, loader: 'null' }, { test: /\.css$/, exclude: helpers.root('src', 'app'), loader: 'null' }, { test: /\.css$/, include: helpers.root('src', 'app'), loader: 'null' } ] } } my Karma.conf.js var webpackConfig = require('./webpack.test'); module.exports = function (config) { var _config = { basePath: '', frameworks: ['jasmine', 'sinon'], files: [ {pattern: './config/karma-test-shim.js', watched: false} ], preprocessors: { './config/karma-test-shim.js': ['webpack', 'sourcemap'] }, plugins:[ require('karma-jasmine'), require('karma-coverage'), require('karma-webpack'), require('karma-phantomjs-launcher'), require('karma-sourcemap-loader'), require('karma-mocha-reporter'), require('karma-sinon') ], coverageReporter: { type : 'html', dir : 'coverage/' }, webpack: webpackConfig, webpackMiddleware: { stats: 'errors-only' }, webpackServer: { noInfo: true }, reporters: ['mocha','coverage'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['PhantomJS'], singleRun: false }; config.set(_config); }; and the karma-test-shim.js Error.stackTraceLimit = Infinity; require('core-js/es6'); require('reflect-metadata'); require('zone.js/dist/zone'); require('zone.js/dist/long-stack-trace-zone'); require('zone.js/dist/proxy'); require('zone.js/dist/sync-test'); require('zone.js/dist/jasmine-patch'); require('zone.js/dist/async-test'); require('zone.js/dist/fake-async-test'); var testContext = require.context('../tests', true, /\.spec\.ts/); testContext.keys().forEach(testContext); var testing = require('#angular/core/testing'); var browser = require('#angular/platform-browser-dynamic/testing'); testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting());
Yuu need to import below code coverage plugin into plugins require('karma-coverage-istanbul-reporter'), Also, use below code to add istanbul reporter property as below coverageIstanbulReporter: { reports: ['html', 'lcovonly'], fixWebpackSourcePaths: true, // enforce percentage thresholds // anything under these percentages will cause karma to fail with an exit code of 1 if not running in watch mode thresholds: { emitWarning: false, // set to `true` to not fail the test command when thresholds are not met global: { // thresholds for all files statements: 80, lines: 80, branches: 80, functions: 80 }, each: { // thresholds per file statements: 80, lines: 80, branches: 80, functions: 80, overrides: {} } } }, The complete config for karma.config.js should be below: // Karma configuration file, see link for more information // https://karma-runner.github.io/0.13/config/configuration-file.html module.exports = function(config) { config.set({ basePath: '', frameworks: ['jasmine', '#angular/cli'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), require('#angular/cli/plugins/karma'), require('karma-htmlfile-reporter'), ], client: { clearContext: false // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { reports: ['html', 'lcovonly'], fixWebpackSourcePaths: true, // enforce percentage thresholds // anything under these percentages will cause karma to fail with an exit code of 1 if not running in watch mode thresholds: { emitWarning: false, // set to `true` to not fail the test command when thresholds are not met global: { // thresholds for all files statements: 80, lines: 80, branches: 80, functions: 80 }, each: { // thresholds per file statements: 80, lines: 80, branches: 80, functions: 80, overrides: {} } } }, angularCli: { environment: 'dev' }, // reporters: config.angularCli && config.angularCli.codeCoverage ? ['spec', 'karma-remap-istanbul'] : ['spec'], // reporters: ['mocha'], reporters: ['progress', 'html', 'kjhtml'], htmlReporter: { outputFile: 'testreports/report.html', // Optional pageTitle: 'Rest Reports', subPageTitle: 'Suite-wise report ', groupSuites: true, useCompactStyle: true, useLegacyStyle: false }, port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false }); };