I'm trying to test (with coverage) my TypeScript application using Karma, Jasmine, and Webpack. With the following, I'm able to successfully run tests, but am unable to generate coverage properly. I'm using karma-remap-coverage
(https://github.com/sshev/karma-remap-coverage) and it seems simple enough.
It looks as though something interesting is happening (and I'm getting some kind of coverage report) but with a few tweaks here and there, the numbers change drastically and I can never actually load the sourcemaps.
Here's the basic setup:
I have a src
directory that contains 10 .ts
files. Only one has a corresponding .spec
file at the moment.
The spec
file is pretty simple and was just enough to prove that I could run tests:
import ComponentToTest from './componentToTest';
describe('ComponentToTest', () => {
it('should run a test', () => {
expect(1+1).toBe(2);
});
it('should be able to invoke the a method', () => {
spyOn(ComponentToTest, 'foo').and.callThrough();
ComponentToTest.foo('testing foo');
expect(ComponentToTest.foo).toHaveBeenCalled();
});
});
This works like a charm when paired with my tsconfig.json
file:
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": false,
"sourceMap": true,
"lib": ["es6", "dom"],
"experimentalDecorators": true
},
"exclude": [
"node_modules"
]
}
and karma.conf.js
file:
module.exports = config => config.set({
frameworks: ['jasmine'],
mime: { 'text/x-typescript': ['ts','tsx'] },
// if I make this a generic './src/**/*.ts' it seems to freeze up
// without throwing any errors or running any tests, but that seems
// like a separate issue...
files: [
'./src/lib/componentToTest.ts',
'./src/lib/componentToTest.spec.ts'
],
preprocessors: {
'./src/**/*.spec.ts': ['webpack'],
'./src/**/*.ts': ['webpack', 'sourcemap', 'coverage']
},
webpack: {
devtool: "source-map",
module: {
rules: [
{
test: /\.ts?$/,
loader: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: [".ts", ".js"]
}
},
webpackMiddleware: {
quiet: true,
stats: {
colors: true
}
},
// add both "karma-coverage" and "karma-remap-coverage" reporters
reporters: ['progress', 'coverage', 'remap-coverage'],
// save interim raw coverage report in memory
coverageReporter: {
type: 'in-memory'
},
// define where to save final remaped coverage reports
remapCoverageReporter: {
'text-summary': null,
html: './coverage/html',
cobertura: './coverage/cobertura.xml'
},
colors: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
And finally, I'm launching the tests with a simple Gulp task:
gulp.task('test', function (done) {
new Server({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, (exitCode) => {
done();
process.exit(exitCode);
}).start();
});
When run, I get an output that seems (mostly) promising:
Chrome 58.0.3029 (Mac OS X 10.12.3): Executed 1 of 2 SUCCESS (0 secs / 0.002 secs)
Chrome 58.0.3029 (Mac OS X 10.12.3): Executed 2 of 2 SUCCESS (0.026 secs / 0.004 secs)
[Error: Could not find source map for: "app/src/lib/componentToTest.ts"]
[Error: Could not find source map for: "app/src/lib/componentToTest.spec.ts"]
========================= Coverage summary =========================
Statements : 43.69% ( 322/737 )
Branches : 15.7% ( 38/242 )
Functions : 35.47% ( 61/172 )
Lines : 44.91% ( 322/717 )
====================================================================
So something is happening! Which makes me feel like I'm close. When I browse to my coverage report in a browser, I see both the .spec.ts
file and the .ts
file listed (which is again, getting closer) but I'm not quite there for a couple of reasons:
.spec.ts
file is being included in the coverage report. Since this is the test file, I do not want to include it.I do feel like I'm pretty darn close. Is there anything simple that I'm missing or suggestions?
Update:
I realized I was using an older version of Node and thought that may be causing some issues. I upgraded to 6.11.0
and while that didn't solve anything, it did provide slightly more context:
The errors are being reported by remap-istanbul
(no surprise there, really):
CoverageTransformer.addFileCoverage (/app/node_modules/remap-istanbul/lib/CoverageTransformer.js:148:17)
I am using [email protected]
which uses [email protected]
- it seems like there have been issues with remap-istanbul
in the past, but not at the version I'm using.
Also using Webpack 2.6.1
and TypeScript 2.3.2
Well, after several days of trying different things, I've finally found a solution that works. I'm not sure specifically what was causing the issue in my first post, but here's where I've ended up. This may be helpful for someone else looking for a really simple TypeScript, Karma, Jasmine, Webpack (with coverage) setup.
spec
file stayed the same.My tsconfig.json
updated to:
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": false,
"inlineSourceMap": true, // this line
"sourceMap": false, // and this one
"experimentalDecorators": true,
"lib": ["es6", "dom"]
},
"exclude": [
"node_modules"
]
}
I switched to using the awesome-typescript-loader
instead of ts-loader
.
And finally, my karma.conf.js
file now looks like:
module.exports = config => config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
frameworks: ['jasmine'],
mime: { 'text/x-typescript': ['ts','tsx'] },
files: [
'node_modules/angular/angular.min.js',
'./src/**/*.ts'
],
preprocessors: {
'./src/**/*.ts': ['webpack']
},
webpack: {
devtool: 'inline-source-map',
module: {
rules: [
{
enforce: 'pre',
test: /\.js$/,
loader: 'source-map-loader',
exclude: [
'node_modules',
/\.spec\.ts$/
]
},
{
test: /\.ts?$/,
use: [
{
loader: 'awesome-typescript-loader',
query: {
/**
* Use inline sourcemaps for "karma-remap-coverage" reporter
*/
sourceMap: false,
inlineSourceMap: true,
compilerOptions: {
removeComments: true
}
},
}
]
},
{
enforce: 'post',
test: /\.(js|ts)$/,
loader: 'istanbul-instrumenter-loader',
exclude: [
/node_modules/,
/\.spec\.ts$/
]
},
{ test: /\.html$/, loader: 'html-loader' }
]
},
resolve: {
extensions: [".ts", ".js", ".html"]
},
externals: {
angular: "angular"
}
},
webpackMiddleware: {
quiet: true,
stats: {
colors: true
}
},
// add both "karma-coverage" and "karma-remap-coverage" reporters
reporters: ['progress', 'coverage', 'remap-coverage'],
// save interim raw coverage report in memory
coverageReporter: {
type: 'in-memory'
},
// define where to save final remaped coverage reports
remapCoverageReporter: {
'text-summary': null,
html: './coverage/html',
cobertura: './coverage/cobertura.xml'
},
colors: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
Final package versions include:
Now my tests run, there are no errors in the console, and I have a coverage report of the original TypeScript files!
Lots of credit to the folks who put this together (it ended up guiding quite a bit of my final solution): https://github.com/AngularClass/angular-starter/tree/master/config
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With