Angular 2 testing karma with webpack Can't find variable: Map - javascript

I am trying to test my directive with karma and webpack.
This is the karma config file
module.exports = function (config) {
config.set({
basePath: './',
frameworks: ["jasmine"],
files: [
{
pattern: 'directive.spec.ts',
watched: false
}],
exclude: [],
preprocessors: {
'directive.spec.ts': ['webpack', 'sourcemap']
},
webpackServer: {
noInfo: true
},
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: [
"PhantomJS"
],
singleRun: true,
reporters: ['mocha'],
webpack: {
resolve: {
extensions: ['', '.ts', '.js'],
modulesDirectories: ['node_modules', '.'],
},
module: {
loaders: [{
test: /\.ts$/,
loader: 'awesome-typescript-loader'
}]
},
stats: {
colors: true,
reasons: true
},
debug: true,
devtool: 'inline-source-map'
}
});
};
And the directive.spec.ts:
import { MyDirective } from './directive';
import {TestComponent} from './test';
import {
async,
inject,
TestBed,
} from '#angular/core/testing';
describe('TestComponent', () => {
let fixture: any;
beforeEach(() => {
fixture = TestBed.configureTestingModule({
declarations: [ TestComponent, MyDirective]
})
.createComponent(TestComponent);
fixture.detectChanges();
});
it('should work', () => {
expect(true).toBe(true);
});
But when I am trying to run my test I am getting this error:
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR ReferenceError: Can't find
variable: Map at directive.spec.ts:1380
What am I missing here?

Please follow these steps. It worked for me:
1) Create a "karma-main.js" file with following code
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('<Source code root folder>', true, /\.spec\.ts/); // Assuming test case files ends with 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());
2) Your karma.conf.js file should look like
var webpackConfig = require('./webpack.config')
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
plugins: [
'karma-jasmine',
'karma-PhantomJS-launcher',
'karma-webpack'
],
webpack: webpackConfig,
// 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: '<relative path to karma-main.js>', watched: false }
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'<relative path to karma-main.js>': ['webpack']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// 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: ['PhantomJS'],
// 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
})
}

Here is my guess: somewhere in the code you use a class Map which appeared in ES6. But PhantomJS doesn't know about this class yet since it's something too new.
So there are 3 choices:
Get rid of usage of Map and use only current JS features (like Object properties) - the cleanest approach.
Use transpiler for transforming your ES6 code into ES5 that's well understood by modern browser. This has huge disadvantages as it will mess with your line numbers and you may have to sacrifice the possibility to debug some of the code.
Use polyfills that implement ES6 features as functions in external libraries (as Sachin Gaur suggested)

Related

Angular 6 Unit testing : how to use test.ts for running karma tests

Under my Angular 6 app , i ve this config
karma.conf.js:
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '#angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('#angular-devkit/build-angular/plugins/karma')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
mime: {
'text/x-typescript': ['ts','tsx']
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, 'coverage'),
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
reporters: config.angularCli && config.angularCli.codeCoverage
? ['progress', 'coverage-istanbul']
: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
browserDisconnectTimeout: 10000,
browserDisconnectTolerance: 3,
browserNoActivityTimeout: 60000,
flags: [
'--disable-web-security',
'--disable-gpu',
'--no-sandbox'
],
singleRun: true,
concurrency: Infinity
});
};
An i ve a file , test.ts ; which is supposed to configurate the test running :
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/jasmine-patch';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async-test';
import { getTestBed } from '#angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '#angular/platform-browser-dynamic/testing';
// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
declare var __karma__: any;
declare var require: any;
// Prevent Karma from running prematurely.
__karma__.loaded = function () {};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /my-component.component.spec.ts/);
// And load the modules.
context.keys().map(context);
// Finally, start Karma to run the tests.
__karma__.start();
i may let me filter file to be tested
for example i want to run this one : my-component.component.spec.ts
But that it not running , and it seems that it lacks some config in the karma.conf to run the test.ts
Sugesstions ?
change this line
const context = require.context('./', true, /my-component.component.spec.ts/);
with this
const context = require.context('./', true, /my-component\.component\.spec\.ts$/);
to avoid the special character '.'

Flow with Jasmine: Assign properties and methods to `this` creates 'Cannot set Property' Error

I am a newbie with "Flow" and I am trying to assign an arbitrary property, e.g. foo, to the keyword this. The purpose of this is to setup my test suite environments cleanly in a beforeEach statement. An example would be something like:
// #flow
describe('test', () => {
beforeEach(() => {
this.foo = 'Hello';
});
it('should bar', () => {
expect(this.foo).toBe('Hello');
});
});
Flow would complain about each this.foo with the following:
Flow: property `foo`. Property not found in global object.
I understand that it's bad practice to inject a property to this, but as mentioned previously, I need to assign to do this (sorry for the pun), to set the state of my tests.
Even though I have this error, I thought my karma test would run fine. When I run my an individual karma test, I would get the following error:
TypeError: Cannot set property 'foo' of undefined
I'm not sure what the problem is. This is my karma configuration setup.
module.exports = function configSettings(config) {
config.set({
// 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: 'test/**/*.js', watched: false},
],
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/**/*.js': ['webpack', 'sourcemap'],
},
webpack: {
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env'],
plugins: ['transform-flow-strip-types']
},
},
},
],
},
devtool: 'inline-source-map',
},
webpackServer: {
noInfo: true,
},
// test results reporter to use
// possible values: 'dots', 'progress'
// Continuous Integration mode
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
logLevel: config.LOG_DEBUG,
// start these browsers
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['ChromeCanary'],
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
});
};

Karma coverage fails to show correct results

I need some help regarding Karma with browserify coverage. I created a repo with the test I am running in here:
https://github.com/jotaoncode/web-istanbul
The results on my coverage are the following:
Results of coverage
The test only runs over the function index. But as you can see the results are a 100% and marks only the first row of the file with a green color.
I have seen cases where istanbul shows correctly the coverage values, I have changed the test and the source but nothing.
I also have this karma configuration:
module.exports = function(config) {
config.set({
//logLevel: 'LOG_DEBUG',
reporters: ['spec', 'coverage'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun : true,
autoWatch : false,
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
port: 9876,
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: [
'mocha',
'browserify'
],
files: [
'src/**/*.js',
'test/*.js'
],
// list of files to exclude
exclude: [],
preprocessors: {
'src/**/*.js': ['browserify', 'coverage'],
'test/**/*.js': ['browserify']
},
coverageReporter: {
reporters: [
{ type: 'html' },
{ type: 'text' },
{ type: 'lcovonly' }
],
instrumenterOptions: {
istanbul: {
noCompact: true
}
},
instrumenter: {
'test/**/*.js': 'istanbul'
},
includeAllSources: true
},
// enable / disable colors in the output (reporters and logs)
colors: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: [
'PhantomJS2'
]
});
};
If you ran the tests you will see that it actually works fine, but the coverage report is not correct.
After doing some research I found this is solved as commented in this issue:
https://github.com/karma-runner/karma-coverage/issues/16
I used browserify-istanbul and now coverage report is working fine :)

How do I use package aliases in Karma? (Example: $ for jquery)

My code depends on tons of other code, and is loaded last in the browser when running from the normal index.html-file. So of course when dependency 1 is jquery, and dependency 2 uses $.html(), and my code is loaded third, that works just fine in the browser.
But in Karma everything screeches to a halt since I'm loading 'jquery' from bower, not '$'.
To be clear: it's not my code that's creating errors, it's the dependencies. I don't get to test my code since everything errors out before then.
So how do I get the tests to work?
Note: I also run everything through webpack so I can use ES6-code, but webpack is loaded in Karma as well, so that should have no effect.
Chrome 45.0.2454 (Mac OS X 10.11.0) ERROR
Uncaught TypeError: Cannot set property '$' of undefined
at /Users/tom/dev/orm/bower_components/jointjs/dist/joint.js:37
Webpack.conf.js:
var webpack = require('webpack');
module.exports = {
devtool: 'source-map-loader',
externals: [
'jquery',
'joint',
'backbone',
'loadash'
],
// entry: './src/index.js',
// output: {
// path: './public',
// filename: 'designer.js'
// },
plugins: [
new webpack.ProvidePlugin({'$': 'jquery', 'jointjs': 'joint'})
],
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
}
};
Karma.conf.js:
// Karma configuration
// Generated on Thu Oct 08 2015 10:54:47 GMT+0200 (CEST)
var webconf = require('./webpack.config.js');
module.exports = function(config) {
config.set({
// 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',
'requirejs',
'bower'
],
// list of files / patterns to load in the browser
files: [
'test-main.js',
{
pattern: 'test/*.js',
included: false
}
],
bowerPackages: [
'jquery',
'jointjs',
'backbone',
'lodash'
],
// list of files to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/*.js': [
'webpack',
'sourcemap'
],
'src/**/*.js': [
'webpack',
'sourcemap'
]
},
webpack: webconf,
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: [
'progress'
],
// 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: [
'PhantomJS',
'Chrome'
],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
I think you're either looking for webpack externals
Webpack Externals
{
externals: {
// require("jquery") is external and available
// on the global var jQuery
"jquery": "jQuery"
}
}
...or, provide plugins.
Provide Plugin vs. Externals
plugins: [
new webpack.ProvidePlugin({
"_": "underscore"
})
]
Most likely provide plugin, because you want to provide that global variable to all the webpacked bundles.
I have no idea what changed, but it now works fine. I include here the final Karma config-file. The webpack-file is identical to the one above.
Note that a couple of configuration changes are actually just normal configuration changes that I've changed since getting it to work.
// Karma configuration
// Generated on Thu Oct 08 2015 10:54:47 GMT+0200 (CEST)
var webconf = require('./webpack.config.js');
module.exports = function(config) {
config.set({
// 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: [
'requirejs',
'bower',
'jasmine',
],
bowerPackages: [
'jquery',
'lodash',
'backbone',
'jointjs'
],
// list of files / patterns to load in the browser
files: [
'test-main.js',
{
pattern: 'test/*.js',
included: false
}
],
// list of files to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/*.js': [
'webpack',
'sourcemap'
],
'src/**/*.js': [
'webpack',
'sourcemap'
]
},
webpack: webconf,
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: [
'progress'
],
// 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,
client: {
captureConsole: false
},
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: [
'PhantomJS',
'Chrome'
],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};

karma coverage shows 0/0, 100% coverage

My coverage numbers are always showing up as 0/0 and 100%. i found a few links pointing to bug reports and documentation but none helped.
here is my config file
module.exports = function (config) {
config.set({
// 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: [
"./CloudConnect.PE.TheApp/Static/CloudConnect.Web.Shared/js/common.js",
"./CloudConnect.PE.Test/node_modules/angular-mocks/angular-mocks.js",
"./CloudConnect.PE.TheApp/Static/CloudConnect.Web.Shared/js/bridge/browser.min.js",
{ pattern: "./CloudConnect.PE.TheApp/Static/CloudConnect.Web.Shared/js/bridge/**/*.js", watched: false, included: false },
{ pattern: "./CloudConnect.PE.TheApp/Static/CloudConnect.Web.Shared/css/**/*.css", watched: false, included: true, served: true },
{ pattern: "./CloudConnect.PE.TheApp/Static/CloudConnect.Web.Shared/images/*.*", watched: false, included: false, served: true },
"./CloudConnect.PE/static/cloudconnect.pe/js/shared.js",
"./CloudConnect.PE.Test/Client/ActWeb/tests/init.spec.js", // always load init.spec.js
"./CloudConnect.PE.ActWeb/static/CloudConnect.PE.ActWeb/js/app.js",
"./CloudConnect.PE.Test/Client/ActWeb/tests/**/*.spec.js"
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
"./CloudConnect.PE.ActWeb/static/cloudconnect.pe.actweb/js/app.js": ["coverage"]
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage'],
coverageReporter: {
type: 'html',
dir: './CloudConnect.PE.Test/Client/coverage/ActWeb'
}
});
};
I had to remove some of the config so SO would let me post. Apparently i had to much code in my post with the full config.
Although the paths are not case sensitive by themselves, the files path and the preprocessors path need to match exactly.
I got it working by changing this:
preprocessors: {
"./CloudConnect.PE.ActWeb/static/cloudconnect.pe.actweb/js/app.js": ["coverage"]
}
to this
preprocessors: {
"./CloudConnect.PE.ActWeb/static/CloudConnect.PE.ActWeb/js/app.js": ["coverage"]
}
All the instructions are missing the bit about setting up webpack with istanbul-instrumenter-loader.
{
test: /\.ts/,
include: helpers.root('src', 'app'),
loader: 'istanbul-instrumenter-loader',
enforce: 'post'
}

Categories