I have a web app written with Typescript 2.4.2, compiled by latest Webpack version (2.7.0).
I'm in the process of adding Karma tests using Jasmine as the assertion library.
This is my karma config file:
'use strict';
const webpack = require('./webpack.config');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const _ = require('lodash');
_.remove(webpack.plugins, plugin => plugin instanceof CleanWebpackPlugin);
webpack.module.rules.forEach(rule => {
if (rule.loader === 'ts-loader') {
rule.exclude = /sg\.d\.ts/;
}
});
module.exports = function (config) {
config.set({
webpack,
mime: {
'text/x-typescript': ['ts','tsx']
},
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
{ pattern: 'app/scripts/**/*.test.ts', watched: true}
],
preprocessors: {
"app/scripts/**/*.test.ts": ["webpack"]
},
// list of files to exclude
exclude: [],
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'mocha'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['jsdom', /*'Chrome'*/],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
On the first test suite I've had no problems, it looks something like this:
import { default as moduleName } from "../module";
import { ListService, IListRequest } from "./listService";
import * as angular from 'angular';
import "angular-mocks";
import "jasmine";
const { module, inject } = angular.mock;
describe("List service", () => {
let serviceToTest: ListService;
let rootScope: ng.IRootScopeService;
let httpBackend: ng.IHttpBackendService;
beforeEach(module(moduleName));
beforeEach(() => {
inject(['$rootScope', '$httpBackend', ListService.SERVICE_NAME,
($rootScope: ng.IRootScopeService, $httpBackend: ng.IHttpBackendService, listService: ListService) => {
serviceToTest = listService;
rootScope = $rootScope;
httpBackend = $httpBackend;
}]);
});
it("service should not be null", () => {
expect(serviceToTest).toBeDefined();
});
// Other tests
});
The problem started when I tried writing a test suite for another service:
import { default as moduleName } from "../module";
import { RedirectionService } from "./RedirectionService";
import * as angular from 'angular';
import "angular-mocks";
import "jasmine";
const { module, inject } = angular.mock;
describe('Redirection service', () => {
});
As you can see the second test suite is empty.
My problem is that as soon as I add that second suite, Angular starts throwing errors - it tries loading Angular and ng-mock twice, once for each new file that imports them.
The error that is thrown is:
Error: [$injector:modulerr] Failed to instantiate module ngLocale due to: RangeError: Maximum call stack size exceeded
A quick Google search produces many thread on the matter - saying this error pops up when Karma loads ng-mock twice. Also, debugging the code on Chrome confirms that it is ngMock that fails to initialize, and Angular produces a warning that Angular was loaded twice.
What can I do about this? It seems to me as if karma treats each test file separately, so it doesn't use Webpack to bundle Angular into a single module but rather compiles each file on its own and adds Angular and ng-mock again.
I've gone a different route, couldn't figure out how to solve that problem.
My webpack config now has this:
And I dropped all the webpack stuff in the Karma config.
I'm telling Webpack to compile another bundle, with a simple entry point TS file that reads:
Karma is watching the output bundle file for changes.