Angular testing with Karma: "module is not defined" - javascript

I know this question has been asked many times, and I know that in most cases people are missing the angular-mocks.js file.
I'm running into the same issue, attempting to test a factory on a module. Unfortunately, I keep running into issues with the tests (why, Angular, oh why must you assume a window and document object?), which state that module is not defined. I'm at a loss. I've also tried using angular.mocks.module, but then I get a message saying Angular isn't defined. What am I doing wrong?
Of note, I'm using gulp as a task runner. My gulpfile (not yet perfect, tasks aren't linked):
var gulp = require('gulp'),
uglify = require('gulp-uglify'),
jshint = require('gulp-jshint'),
jasmine = require('gulp-jasmine'),
karma = require('gulp-karma'),
paths = {
scripts: "scripts/*.js",
spec: "spec/*.js",
dist: "dist"
};
gulp.task('prepare', function () {
return gulp.src(paths.scripts)
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(uglify())
.pipe(gulp.dest(paths.dist))
});
gulp.task('test', function () {
gulp.src([paths.scripts, paths.spec])
.pipe(karma({
configFile: 'karma.conf.js',
action: 'run'
}));
});
gulp.task('default', ['prepare', 'test']);
My karma.conf.js, generated by karma init:
// Karma configuration
// Generated on Fri Mar 14 2014 14:24:30 GMT-0400 (EDT)
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: [
'./lib/angular/angular.min.js',
'./lib/angular-mocks/angular-mocks.js',
'./src/*.js',
'./spec/*.js'
],
// 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: false,
// 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
});
};
And finally, my test suite (nothing's set up yet, if I can pass this hurdle, we'll be good):
/* Tests for memento.js. */
describe('memento core test suite', function () {
var memento;
beforeEach(module('Memento'));
beforeEach(function() {
inject(function(_memento_) {
memento = _memento_;
});
});
// Check functions.
// check to see if it has the expected function
it('should match expected interface', function () {
expect(angular.isFunction(memento.canUndo)).toBe(true);
expect(angular.isFunction(memento.canRedo)).toBe(true);
expect(angular.isFunction(memento.undo)).toBe(true);
expect(angular.isFunction(memento.redo)).toBe(true);
expect(angular.isFunction(memento.push)).toBe(true);
});
it('should initialize', function () {
this.fail(Error('Test not implemented'));
});
it('should push() a changed object', function () {
this.fail(Error('Test not implemented'));
});
it('should not push() an unchanged object', function () {
this.fail(Error('Test not implemented'));
});
it('should return original object on undo()', function () {
this.fail(Error('Test not implemented'));
});
it('should return modified object on redo()', function () {
this.fail(Error('Test not implemented'));
});
it('should not undo() if at beginning of stack', function () {
this.fail(Error('Test not implemented'));
});
it('should not redo() if at end of stack', function () {
this.fail(Error('Test not implemented'));
});
// TODO: Implement revert to original, clearing history.
//
// it('should return seed object on revert()', function () {
// this.fail(Error('Test not implemented'));
// });
// it('should clear the stack on clear()', function () {
// this.fail(Error('Test not implemented'));
// });
});
Does anyone see anything awry? I'm not sure if there's something really obvious I'm missing - I could use an extra set of eyes, or many. I originally thought I'd be able to run this as a simple Jasmine test suite without Karma, but due to Angular, that has problems. If I can't get this to work, I might just use npm's Angular package and alter my Angular module so that it supports CommonJS...
Thanks, everyone! Hope I'm not crazy.
Edit: I've included my devdependencies.
"devDependencies": {
"gulp": "~3.5.6",
"gulp-uglify": "~0.2.1",
"gulp-jshint": "~1.5.0",
"gulp-jasmine": "~0.2.0",
"angular": "~1.2.10",
"karma": "~0.12.0",
"gulp-karma": "0.0.4",
"karma-jasmine": "~0.2.2",
"karma-chrome-launcher": "~0.1.2"
}

The message stating that module/angular is not defined means that your angular-mocks.js file is not being loaded, despite the fact you have it listed in your karma.conf.js file.
The problem you're experiencing is gulp-karma ignoring your karma.conf.js files array. This happens when you pass a string or glob into gulp.src in the gulpfile.
To work around this, pass gulp.src a string for a bogus file, "./foobar" for instance, and this will cause the files array in the karma.conf.js file to be used instead.
gulp.task('test', function () {
gulp.src('./foobar')
.pipe(karma({
configFile: 'karma.conf.js',
action: 'run'
}));
});
Hope this helps!
Reference:
https://github.com/lazd/gulp-karma/issues/9

This is not the answer to your particular issue,
but I had a similar symptom in a very similar scenario.
However, the root cause was different,
so I'll share it here in case others find this post and they have the same issue I had.
In my case, because I introduced tests later in the game,
there was a mismatch between the versions of angular (1.4.7) and angular-mocks (1.6.9).
I found out this was the root cause
by using the debug of Karma in the browser.
Lowering the version of angular-mocks to match angular solved the issue.

Related

Karma/Jasmine tests are failing due to: TypeError: MysmartdevicesCtrl is undefined

My angularjs tests are all failing due to the controller being undefined. I tried several different solutions yet nothing is working. I've added every js file i thought was needed in karma, from the looks of it I don't think the beforeEach(inject... function is getting called or if it is then something isnt getting set right. I added print statements along the way but nothing ever gets printed in the beforeEach(inject... function call.
Error Log:
Firefox 49.0.0 (Ubuntu 0.0.0) Controller: RegisteruserCtrl should attach a list of awesomeThings to the scope FAILED
minErr/<#bower_components/angular/angular.js:68:12
loadModules/<#bower_components/angular/angular.js:4640:15
forEach#bower_components/angular/angular.js:321:11
loadModules#bower_components/angular/angular.js:4601:5
createInjector#bower_components/angular/angular.js:4523:19
workFn#bower_components/angular-mocks/angular-mocks.js:3074:44
[3]</ContextKarma/this.loaded#http://localhost:9876/context.js:151:7
TypeError: RegisteruserCtrl is undefined in test/spec/controllers/registeruser.js (line 21)
#test/spec/controllers/registeruser.js:21:5
[3]</ContextKarma/this.loaded#http://localhost:9876/context.js:151:7
Firefox 49.0.0 (Ubuntu 0.0.0): Executed 3 of 3 (3 FAILED) ERROR (0.17 secs / 0.09 secs)
registerCtrl.js Spec:
'use strict';
describe('Controller: RegisteruserCtrl', function () {
// load the controller's module
beforeEach(module('clientApp'));
var RegisteruserCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
RegisteruserCtrl = $controller('RegisteruserCtrl', {
$scope: scope
// place here mocked dependencies
});
}));
it('should attach a list of awesomeThings to the scope', function () {
expect(RegisteruserCtrl.awesomeThings.length).toBe(3);
});
});
karma.conf.js
// Karma configuration
// Generated on Tue Oct 11 2016 18:25:32 GMT-0500 (CDT)
"use strict";
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: [
'bower_components/angular/angular.js',
'bower_components/angular-route/angular-route.js',
'bower_components/angular-mocks/angular-mocks.js',
'app/**/app.js',
'app/Common/*.js',
'app/scripts/controllers/*.js',
'test/**/*.js'
],
// 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: {},
plugins: [
'karma-firefox-launcher',
'karma-chrome-launcher',
'karma-jasmine',
],
// 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: ['Firefox'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
};
Using the minimatch pattern (/**/*):
'app/**/app.js',
'app/Common/*.js',
caused me a lot of trouble. Instead of doing that way explicitly write the name of the controller (or file) you need. For example:
app/Common/RegisteruserCtrl.js
Here's an example that works for me:
files: [
'./node_modules/angular/angular.js', // angular
'./node_modules/angular-mocks/angular-mocks.js', // angular-mocks
'./app/views/js/controllers/sugestionController.js'
],

karma testing - services injection error

i have inhereted a angular project that uses npm, grunt, bower ... and karma + jasmin.
i have been asked to setup some tests for the project using karma and jasmin.
karma has already been setup in the project but never used.
when i run 'grunt test' i get injection errors on all of the services, like the following.
Error: [$injector:unpr] Unknown provider: excelparserserviceProvider <- excelparserservice
http://errors.angularjs.org/1.2.6/$injector/unprp0=excelparserserviceProvider%20%3C-%20excelparserservice
there is already a karma.conf.js looking like this.
i havent changed anything in the karma.conf file, except adding some of the libaries that used in the project into the list under Files: [].
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// testing framework to use (jasmine/mocha/qunit/...)
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'app/bower_components/angular/angular.js',
'app/bower_components/angular-mocks/angular-mocks.js',
'app/bower_components/angular-resource/angular-resource.js',
'app/bower_components/angular-cookies/angular-cookies.js',
'app/bower_components/angular-sanitize/angular-sanitize.js',
'app/bower_components/angular-route/angular-route.js',
// i manually added the ones from here
'app/bower_components/jquery/dist/jquery.js',
'app/bower_components/geocoder-js/dist/geocoder.js',
'app/bower_components/js-xlsx/dist/xlsx.core.min.js',
'app/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
'app/bower_components/d3/d3.js',
'app/bower_components/angular-file-upload/angular-file-upload.js',
// to here.
'app/scripts/*.js',
'app/scripts/**/*.js',
'test/mock/**/*.js',
'test/spec/**/*.js'
],
// list of files / patterns to exclude
exclude: [],
// web server port
port: 8080,
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: ['Chrome'],
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};
the paths,
'app/scripts/*.js' --> leads to app.js and a config.js
'app/scripts/**/*.js' -->leads to all services controllers and directives
'test/mock/**/*.js' --> is non existent
'test/spec/**/*.js'--> contains all the test files
there are test files corresponding to every part of the applikation. Which i have been told has been auto generated. So i find it weird if they should contain the error. but the one related to the excpelparserservice injection error is.
'use strict';
describe('Service: excelparserservice', function () {
// load the service's module
beforeEach(module('batchUploadApp'));
// instantiate service
var Excelparserservice;
beforeEach(inject(function (_excelparserservice_) {
Excelparserservice = _excelparserservice_;
}));
it('should do something', function () {
expect(!!Excelparserservice).toBe(true);
});
});
the declaration of the service looks like this.
'use strict';
angular.module('batchUploadApp')
.service('ExcelParserService',
function ExcelParserService($q, ExcelvalidationService, GeoLocationService) {
the application in general works.
hope i my explication is usefull :)
thank you.
You define and register your service like this:
angular.module('batchUploadApp').service('ExcelParserService', ...
meaning that you register it under the name ExcelParserService. On the other hand, when you try to inject the service into you test, you use its name in lowercase:
beforeEach(inject(function (_excelparserservice_) {
Both names must match, thus the solution is to change the name of the parameter:
beforeEach(inject(function (_ExcelParserService_) {

Testing Angular with Gulp-mocha: "Window is not Defined"

I am setting up a project with Gulp to run unit tests with Mocha, including Angular tests. I have the basic set up working (indexOf, etc.), however when I include angular-mocks I get this error or a node-module error:
ReferenceError in 'gulp-mocha': "Window is not defined"
I've tried including angular-module-mocks, using gulp-mocha-phantomjs... but the result is the same. (With mocha-phantomjs my error was 'Init timeout'.) I've seen many examples of configurations with Mocha and Angular or Gulp and Karma but have not yet found a solution for Gulp, Mocha and Angular alone.
I'm thinking of something similar to this Karma solution to correctly load angular-mocks by specifying it in a config file and forcing Gulp to load it (Angular testing with Karma: "module is not defined"). However, even if this would work, it seems like gulp-mocha does not support loading a configuration file (mocha.opts - https://github.com/sindresorhus/gulp-mocha/issues/26). I would be happy to hear a more straightforward solution.
I am using angular-mocks 1.2.22 and gulp-mocha 1.1.0.
Code snippets:
var mocha = require('gulp-mocha');
gulp.task('test', function () {
return gulp.src('test/*.js', {read: false})
.pipe(mocha({reporter: 'nyan', timeout: 400}));
});
test/test.js
var assert = require('assert');
var angular_mocks = require('angular-mocks'); //Fails only when this line is present
//tests
What finally worked for me with Gulp/Browserify/Mocha was using Karma and Mocha combined.
Specifically, I used gulp-karma, and defined the configuration at karma.config.js and used a dummy file for gulp.src as others have done:
gulp.task('test', function () {
return gulp.src('./foobar.js').pipe(karma({
configFile:'karma.config.js',
action: 'run'
}))
.on('error', handleErrors);
});
Then I used this karma.config.js file. I needed the npm modules karma-mocha, karma-chai, and karma-bro. (With only the first two, I was getting 'require is not defined'. Then of course I tried including karma-requirejs, but that does not work with Browserify. Then I tried karma-commonjs, which still didn't work. Then I tried karma-browserify, and got a strange error involving bundle() that no one seems to have solved (https://github.com/xdissent/karma-browserify/issues/46). Karma-bro did the trick.)
I also needed to preprocess each file referenced in the tests as well as the tests themselves. (For using phantomJS also include karma-phantomjs-launcher. And I am using the bower version of angular-mocks simply because it is more recent: v1.2.25 compared to 1.2.22 for npm - but the npm version might work.)
module.exports = function(config) {
config.set({
basePath: '',
// frameworks to use
frameworks: ['browserify', 'mocha', 'chai'],
// list of files / patterns to load in the browser
files: [
'node_modules/angular/lib/angular.min.js',
'bower_components/angular-mocks/angular-mocks.js',
'source/javascript/controllers/*.js',
'source/javascript/*.js',
'test/*.js'
],
reporters: ['progress'],
port: 9876,
colors: true,
autoWatch: true,
browsers: ['PhantomJS'],
preprocessors: {
'source/javascript/controllers/*.js': ['browserify'],
'source/javascript/*.js': ['browserify'],
'test/*.js': ['browserify']
}
});
};
And finally this test passes. At the end I needed to make sure the names of my modules and controllers were consistent (capitals etc.) to resolve 'Module not defined' errors. For debugging I replaced node_modules/angular/lib/angular.min.js with node_modules/angular/lib/angular.js in the files.
describe('Angular', function() {
describe('App Controllers', function() {
beforeEach(angular.mock.module('App'));
describe('MessageCtrl', function() {
it('should retrieve the correct amount of messsages', angular.mock.inject(function($controller) {
var scope = {},
ctrl = $controller('MessageCtrl', {$scope:scope});
assert.equal(scope.messages.length, 2);
}));
});
});
});
I do get this: 'WARNING: Tried to load angular more than once.' I can live with it.

Karma gives me errors when running tests (related to backbone.js)?

My error is related to backbone.js 'undefined' is not an object (evaluating '_.each') it's pointing to line 227 which is inside my test.js script which was compiled by browserify.
This line is a built-in block within backbone, so the actual issue can't be within that line obviously.
So my setup... I am testing a simple module here, it's Inside ./client/src/views/.
// intro.js
var Backbone = require('backbone');
module.exports = IntroView = Backbone.View.extend({
el: '.intro',
initialize: function() {
this.render();
},
render: function() {
this.$el.height($(window).height() - 10);
}
});
Then I have the actual test module inside ./client/spec/views/
// intro.test.js
var IntroView = require('../../src/views/intro.js'),
$ = require('jquery');
describe('view:intro', function() {
var introView = new IntroView();
it('just testing if I can get a success', function() {
expect(1 + 2).toEqual(3);
});
it('should render the view', function() {
introView.render();
});
});
Okay so I run gulp browserify to compile the script like this
gulp.task('browserify:tests', function() {
return gulp.src('./client/spec/views/intro.test.js')
.pipe(tasks.browserify({
transform: ['hbsfy', 'browserify-shim']
}))
.pipe(tasks.concat('tests.js'))
.pipe(gulp.dest('./test'));
});
Then inside my karma.config.js
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// frameworks to use
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'./test/tests.js',
],
// list of files to exclude
exclude: [
],
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
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: false,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera (has to be installed with `npm install karma-opera-launcher`)
// - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
// - PhantomJS
// - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
browsers: ['PhantomJS'],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: true
});
};
Lastly I run karma start in the command line. So I hope I am using karma the right way, I think I am but if I want to test my code which uses backbone I need to get past this hump.
So my question is what am I doing wrong, why is the error occurring within the backbone.js code? Also am I doing it the right way?
I had the same error, but it was caused by using modules maping in my requirejs config. I've solved it by using paths instead (i've overwrite my browser config).
Your problem is most likely that you didn't have requirejs config. See requirejs config page for further instructions.

Karma E2E Tests found but skipped and marked as fail

Given the e2e config:
module.exports = function(config) {
config.set({
basePath: '../',
files: [
'E2E/**/*.js'
],
autoWatch: false,
browsers: ['Chrome'],
frameworks: ['ng-scenario'],
singleRun: true,
proxies: {
'/': 'http://localhost:8000/'
},
plugins: [
'karma-junit-reporter',
'karma-chrome-launcher',
'karma-jasmine',
'karma-ng-scenario'
],
junitReporter: {
outputFile: 'test_out/e2e.xml',
suite: 'e2e'
},
urlRoot: '/_karma_/'
});
};
and the scenario:
'use strict';
/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */
describe('Mailing App', function () {
it('should filter the phone list as user types into the search box', function () {
expect(true).toBe(true);
});
it('should filter the phone list as user types into the search box', function () {
expect(Element('foo').count()).toEqual(1);
});
describe('Sample Test', function () {
beforeEach(function () {
browser().navigateTo('../../Client/Views/Shared/_Layout.cshtml');
});
it('should filter the phone list as user types into the search box', function () {
pause();
expect(Element('.ng-binding')).toBeDefined();
});
});
});
The programs finds the 3 tests but does not pass or fail them, rather skips them.
Running the script (with windows 8.1, git bash) returns says:
Karma v0.12.1 server started atHTTP://localhost:9876/karma/"
starting Chrome Connected on Socket Chrome 31.0.1650 Executed 0 of 3
(skipped 3) Error
Any idea why tests that don't even need to traverse the site or look at the DOM etc can be found but can not be run?
Ok, not sure if this will help anyone but basically the issue was I didn't realise that angular-scenario.js is not part of the Karma test running suite, it is from before karma when tests were running with testacular.
angular-scenario.js was being included as part of the file includes with the */.js wildcards.
Once I changed it to no longer see that it seems to now be working, guess I would have expect some kind of conflicting functions or stuff not defined to be thrown, if classes were messing each other up.

Categories