Karma Coverage and Babel+Browserify Preprocessing - javascript

I'm using Karma to test my ES6 code. When I add karma-coverage to the mix, I need to add all the source files for the coverage tool to make a useful report, but when I do that, Karma gives me this error in all browsers:
PhantomJS 1.9.8 (Mac OS X 0.0.0) ERROR
Error: Invariant Violation: _registerComponent(...): Target container is not a DOM element.
at /var/folders/55/9_128mq95kz1q_2_vwy7qllw0000gn/T/41cf272955d73fbba8ad1df941172139.browserify:46444:0 <- ../../node_modules/react/lib/invariant.js:49:0
My Karma config file is:
basePath: '',
browserNoActivityTimeout: 100000,
frameworks: ['phantomjs-shim', 'mocha', 'chai', 'browserify'],
files: [
'./client/**/*.js',
'./client/**/*.spec.js'
],
exclude: [
'./client/dist/*.js',
],
preprocessors: {
'./client/**/*.js': ['browserify', 'sourcemap', 'coverage']
},
browserify: {
debug: true,
transform: [
['babelify', {
optional: ["runtime"],
plugins: ["rewire"]
}],
]
},
coverageReporter: {
instrumenters: { isparta : require('isparta') },
instrumenter: {
'**/*.js': 'isparta'
},
type : 'html',
dir : './coverage/'
},
reporters: ['mocha', 'coverage'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['Chrome', 'Firefox', 'Safari', 'PhantomJS'],
singleRun: true
If I remove './client/**/*.js', from the files array, the tests work, but then the coverage only show me the tests code. I use Karma from gulp with gulp-karma, but I suppose that this doesn't have anything to do with the problem.

I had that same problem, which in my case occurred because React couldn't find the element in which it needed to render the html.
I found a quick fix by adding the following if statement into my main js file:
if ($('#container').length <= 0) {
$('body').prepend('<div id="container"></div>');
}
ReactDom.render(
<App />,
document.getElementById('container')
);
I'm aware this must not be the best way of fixing it, but at least it works for now. If anyone knows of a better way, please let us know!

Code you are covering is trying to render component into DOM node. Your code relys that it already exists (somewhere in index.html or whatever). But PhantomJS cannot find that DOM node.
You should create it before calling ReactDOM.render or search how to change template of html page used by phantom to run tests (there are plugins doung this).

Related

Solving Dependency Resolution of source files in karma

We have built our application using UI5 library and written jasmine tests for these. We have difficulty in gettting the coverage for these javascript files.
Project Structure:
Currently, our project structure consists of the typical model, view, controller structure. We have around 1000 files kept in different hierarchies.
Problem at hand:
I am trying to get coverage for this project and trying out Karma for this.
With the default karma configuration, I ran the tests. The tests failed and based on the logs I could see that karma expects all the files in the project to be listed in the order of their dependencies. This would be extremely difficult for me as the number of files is huge.
Questions:
Is my understanding of Karma right? Is providing all the files in the order of their dependency the only way?
Does anyone know any alternate solution or alternate library where I can get coverage for my javascript files?
The complete karma.config.js
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', 'openui5'],
openui5: {
path: "https://sapui5.hana.ondemand.com/resources/sap-ui-core.js",
useMockServer: false
},
client: {
openui5: {
config: {
theme: 'sap_bluecrystal',
libs: 'sap.m,sap.bpm',
resourceRoots: {
"sap.bpm": "base/target/appresources/com/sap/bpm",
}
}
}
},
files: [
'src/**/*.js' , 'test/**/*.js'
],
preprocessors: {
'test/**/*.js': ['coverage']
},
captureTimeout: 210000,
browserDisconnectTolerance: 3,
browserDisconnectTimeout: 210000,
browserNoActivityTimeout: 210000,
plugins: [
'karma-jasmine',
'karma-coverage',
'karma-chrome-launcher',
'karma-openui5',
'karma-requirejs'
],
reporters: ['progress', 'coverage'],
port: 9878,
colors: true,
logLevel: config.LOG_DEBUG,
autowatch: false,
browsers: ['Chrome'],
singleRun: true,
concurrency: Infinity,
coverageReporter: {
includeAllSources: true,
dir: 'coverage/',
reporters: [
{ type: "html", subdir: "html" },
{ type: 'text-summary' }
]
}
});
};
Ok so : in the preprocessor entry, you have to specify which files you want to instrument for coverage.
In your conf file you set the test files for instrumentation, which is very unlikely to be what you want to achieve
switching to
preprocessors: {
'src/**/*.js': ['coverage']
},
is likely to give you better results :)

[karma]: Error: Unable to resolve module [expose-loader?jQuery!jquery]

I'm trying to setup karma tests for typescript.
karma.conf.js
module.exports = function (config) {
config.set({
frameworks: ['jasmine', 'karma-typescript'],
files: [
{pattern: 'src/main/**/*.ts'}, // Actual code
{pattern: 'src/test/**/*.ts'}, // Unit tests
],
preprocessors: {
'src/main/**/*.ts': ['karma-typescript', 'coverage'],
'src/test/**/*.ts': ['karma-typescript']
},
reporters: ['progress', 'junit', 'coverage'],
// the default configuration
junitReporter: {
...
},
coverageReporter: {
type: 'lcov',
subdir: '.',
dir: 'target/'
},
browsers: ['PhantomJS'],
singleRun: true,
autoWatch: true,
logLevel: config.LOG_INFO,
colors: true,
port: 9876
});
};
the code itself has nothing yet but:
import "expose-loader?jQuery!jquery";
import "expose-loader?Tether!tether";
import "../scss/main.scss";
import "bootstrap";
and the test :
it("should expose jquery to window", () => {
expect(window["jQuery"]).toBeDefined();
expect(window["$"]).toBeDefined();
});
The problem I have is an error that karma is not able to understand expose-loader from webpack giving an error:
ERROR [karma]: Error: Unable to resolve module [expose-loader?jQuery!jquery]
could someone please shed some light on this.
Without expose-loader if I do put jquery manually everything work perfectly fine, but I want just to do it properly.
Thanks!
the problem was in including actual code in "files" rather than importing the class I'm going to test. So I've made
{pattern: 'src/main/**/!(file with expose-loader).ts', include:'false'}
and excluding file that responsible for exposing global objects

Webpack Karma using react/addons

I have a large-ish Angular app written in Typescript generating JS files 1:1 plus external modules such as moment and React loaded off the same server. Dependencies are handled by RequireJS.
We added some basic Angular Karma tests which worked fine. This uses a duplicate RequireJS config tweaked to load the tests into Karma.
Now I am trying to test some React components and in the process move to Webpack. So, I have modified the Karma config to use Webpack and installed the external dependencies using npm. I have spent all day trying to get this to work but I cannot find a solution which works for my setup.
karma.conf.js
var path = require('path');
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'],
// list of files / patterns to load in the browser
files: [
'ng/*.js',
'ng/**/*.js',
'ng/**/tests/*.spec.js'
],
// list of files to exclude
exclude: [
'app.js', // Old requirejs config
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'*.js': ['webpack', 'sourcemap'],
'ng/**/*.js': ['webpack', 'sourcemap'],
'partials/**/*.html': ['ng-html2js']
},
webpack: { //kind of a copy of your webpack config
devtool: 'inline-source-map', //just do inline source maps instead of the default
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
exclude: path.resolve(__dirname, 'node_modules'),
query: {
presets: ['airbnb']
}
},
{
test: /\.json$/,
loader: 'json',
},
{
test: /\.ts$/,
loader: 'typescript',
},
],
},
externals: {
'react': true,
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true
}
},
webpackServer: {
noInfo: true //please don't spam the console when running in karma!
},
// 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'
],
plugins: [
'karma-webpack',
'karma-sourcemap-loader',
'karma-requirejs',
'karma-ng-html2js-preprocessor',
//'karma-firefox-launcher',
'karma-chrome-launcher',
'karma-phantomjs-launcher',
'karma-jasmine'
],
babelPreprocessor: {
options: {
presets: ['airbnb']
}
},
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultanous
concurrency: Infinity,
});
};
This is what I am getting:
PhantomJS 2.1.1 (Linux 0.0.0) ERROR
ReferenceError: Can't find variable: react
at /vagrant/app/media/website/js/ng/chartApp.js:48060 <- webpack:/external "react/addons":1:0
How should I be setting this up?
This might be happening if you're using Enzyme, which uses some lazy require() calls to maintain compatibility with React 0.13 and 0.14, so Webpack isn't bundling them.
If that's the case, put this in your karma.config.js:
webpack: {
// ...whatever else you have...
externals: {
'cheerio': 'window',
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true
}
}
If you're not using Enzyme, this might still be a solution (at least the react/addons part).
See this Karma page for details.
Here's your first problem:
"I have a large-ish Angular app written in Typescript generating JS files 1:1 plus external modules such as moment and React loaded off the same server. Dependencies are handled by RequireJS."

Karma fails when using PhantomJS but not Chrome

I have a series of tests that are pass when I use the Karma Chrome Launcher but fail when I use the Karma PhantomJS launcher.
Here is my what's inside my karma.config.js file
```
frameworks: ['browserify','mocha','chai', 'sinon'],
files: require('./include.conf.js').concat([
'test/helper/*.js',
'test/example/*.spec.js',
'test/unit/*.spec.js',
'test/integration/*.spec.js'
]),
// list of files to exclude
exclude: [
'gulpfile.js',
'index.js',
'karma.conf.js'
],
browserify: {
debug: true,
transform: ['reactify'],
bundleDelay: 1000
},
preprocessors: {
'test/helper/*.js': ['browserify'],
'test/example/*.spec.js': ['browserify'],
'test/unit/*.spec.js': ['browserify'],
'test/integration/*.spec.js': ['browserify'],
'dev/js/**/*.js': ['browserify']
},
// web server port
port: 9876,
autoWatch: true,
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
plugins: [
'karma-coverage',
'karma-mocha',
'karma-browserify',
'karma-chai',
'karma-sinon',
'karma-phantomjs-launcher'
]```
All of the files are being preprocessed and running properly with the Karma Chrome Launcher, but when I try to run them with PhantomJS, I get a bunch of errors like this :
PhantomJS 1.9.8 (Mac OS X 0.0.0) ERROR
ReferenceError: Can't find variable: require
at /Users/edwinlin/Documents/repos/Picarus/dev/js/utils/database-utils.js:1
Thanks for anyone's help!

Error In Getting AngulaJS + Angular AMD + RequireJS to Work with Karma and Jasmine

I ma trying to add Karma & Jasmine+Require Js based Unit testing support for an AngularJS +Angular AMD & RequireJS Application that I have created. I have been wrecking my brain around this for two days now but I am still nowhere close to sealing the deal.
I keep getting the error :
INFO [karma]: Karma v0.12.21 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 36.0.1985 (Mac OS X 10.9.4)]: Connected on socket 8oFHaa2hqJPs0ecgIXCa with id 31963369
Chrome 36.0.1985 (Mac OS X 10.9.4) ERROR: 'There is no timestamp for ../www/scripts/specs/UserControllerTest.js!'
WARN [web-server]: 404: /www/scripts/specs/UserControllerTest.js
Chrome 36.0.1985 (Mac OS X 10.9.4) ERROR
Uncaught Error: Script error for: specs/UserControllerTest
http://requirejs.org/docs/errors.html#scripterror
at /usr/local/lib/node_modules/requirejs/require.js:141
My Code is as follows :
The Karma Config file :
// Karma configuration
// Generated on Fri Aug 15 2014 20:49:40 GMT+1000 (EST)
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'],
// list of files / patterns to load in the browser
files: [
'test-main.js',
{pattern: 'specs/*.js', included: true}
],
// 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 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: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
My test-main.js file.
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
var pathToModule = function(path) {
return path.replace(/^\/base\//, '').replace(/\.js$/, '');
};
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(pathToModule(file));
}
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '../www/scripts',
// alias libraries paths
paths: {
'angular': '../libs/angular',
'angular-route': '../libs/angular-route',
'angular-animate':'../libs/angular-animate',
'angular-mocks':'../libs/angular-mocks',
'angularAMD': '../libs/angularAMD.min',
'Framework7':'../libs/framework7',
'UserController':'controller/UserCtrl',
'WebCallManager':'services/WebCallManager'
},
// Add angular modules that does not support AMD out of the box, put it in a shim
shim: {
'angularAMD': ['angular'],
'angular-route': ['angular'],
'angular-animate':['angular'],
'angular-mocks':['angular'],
'Framework7':{exports: 'Framework7'}
},
//kick start application
//deps: ['app'],
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
And My Unit Test is :
describe('UserController', function () {
var scope,controller;
//mock Application to allow us to inject our own dependencies
beforeEach(angular.mock.module('app'));
//mock the controller for the same reason and include $rootScope and $controller
beforeEach(angular.mock.inject(function($rootScope, $controller) {
//create an empty scope
scope = $rootScope.$new();
//declare the controller and inject our empty scope
$controller('UserController', {$scope: scope});
}));
it('checks the controller name', function () {
expect(scope.name).toBe('Superhero');
});
});
I have uploaded all my code of my project to link here. Anyone who can help me with this is highly appreciated. I think In am at the end of my tether with this.
marcoseu is right, the There is no timestamp for... error means karma cant find the the file, but there is more.
I'd recommend making karma's base path your project root. This avoids Karma making the file paths absolute instead of relative which keeps things simpler and avoids path reference problems (at least on my windows OS).
Your test should be a require module (i.e. using define) so it can be sure the objects it requires are fully loaded. See the example test at http://karma-runner.github.io/0.12/plus/requirejs.html
karma.config.js
basePath: "../",
files: [
'test/test-main.js',
{pattern: 'test/specs/*.js', included: false},
{pattern: 'www/**/*.js', included: false},
],
Now your files are all served by Karma under /base.
test-main.js
require.config({
baseUrl: "/base/www/scripts",
Debugging
But most importantly you can debug all of this. Run Karma, switch to the Karma created chrome instance, click the debug button, open the chrome developer tools. Check the console, and your source files. Especially the source of debug.html, as at the bottom it has the definition of all your karma served files.
You can also set breakpoints and then refresh the page to watch the tests being executed. You will be able to see for yourself why you are getting test errors. Win.
The error There is no timestamp for... means that karma is unable to access the file in question. You need to define the www directory so that is is accessible by karma. Try the following:
karma.config.js
files: [
'test-main.js',
{pattern: './specs/*.js', included: true},
{pattern: '../../www/**/*.js', included: false}
],
Take a look at karma.conf in the angularAMD project and the Karma documentation for files.

Categories

Resources