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
});
};