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_) {
Related
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.
when i try running the karma test runner, i'm getting a error as the following from one of my files, saying that my library google is undefined???
Chrome 36.0.1985 (Mac OS X 10.9.4) ERROR
Uncaught ReferenceError: google is not defined
at /Users/giowong/rails_project/doctible_pre_treatment/app/assets/javascripts/angular-google-maps.min.js:7
my karma.conf.js file
// Karma configuration
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '/Users/giowong/rails_project/doctible_pre_treatment/',
// testing framework to use (jasmine/mocha/qunit/...)
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'app/assets/components/angular/angular.js',
'app/assets/components/angular-mocks/angular-mocks.js',
'app/assets/components/angular-resource/angular-resource.js',
'app/assets/components/angular-payments/lib/angular-payments.js',
'app/assets/components/ng-file-upload/angular-file-upload.js',
'app/assets/components/ngDialog/js/ngDialog.js',
'app/assets/components/angular-route/angular-route.js',
'app/assets/components/angular-loading-bar/src/loading-bar.js',
'app/assets/javascripts/angular/filters/widget-filters.js',
'app/assets/components/angular-animate/angular-animate.js',
'app/assets/javascripts/angular/directives/loader.js',
'app/assets/javascripts/angular/directives/focus.js',
'app/assets/javascripts/angular/directives/checkout-form.js',
'app/assets/javascripts/angular/directives/provider-form.js',
'app/assets/components/angular-ui-utils/ui-utils.js',
'app/assets/components/angular-sanitize/angular-sanitize.js',
'app/assets/components/angular-bootstrap/ui-bootstrap.js',
'app/assets/components/angular-ui-map/ui-map.js',
'app/assets/components/underscore/underscore.js',
'app/assets/components/jquery-1.11.1.min.js',
'app/assets/javascripts/*.js',
'app/assets/javascripts/**/**/*.js',
'spec/javascripts/*.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: true,
// 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: true
});
};
i tried google already and no luck so far. I've tried making a test file and defining google itself. Any help is appreciated
You get this error because you use google maps v3 API on your application but do not have any code, which will initialize window.google property, when you run your tests.
Solution 1
Compile this mock to javascript and reference compiled *.js in files of your config.
Solution 2
Create your own google-mock.js
Add it to files array of your karma.config
Add stab to google-mock.js for each Google Maps API call which you use in your app
like in example below:
(function(){
window.google = window.google || {
maps: {
Map: function(){},
// and so on...
}
};
})();
Solution 3
Open this link
Save ALL text from this page to file google-maps-api.js
Add path to this file to your files array in karma.config
In my case in the files section of karma.conf.js I needed the google api with "js" extension (not .ts!):
files:[
'src/app/shared/mocks/google-api.js'
],
I have copied and pasted the real google API from the url:
"https://maps.googleapis.com/maps/api/js?sensor=false"
If you pass the url it won´t work.
It´s not the a cool solution, but for now it works at least.
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.
I'm very new to testing but thought it was a good idea to start out some testing with this project. When I run grunt karma:watch I get the error with this configuration files.
I have a config file containing:
module.exports = function(config) {
config.set({
basePath: '../..',
// testing framework to use (jasmine/mocha/qunit/...)
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'src/js/vendors/angular.js',
'src/js/vendors/angular-mock.js',
'src/js/app/navigation/*js',
'src/**/*.js',
'src/js/vendors/*.js',
'src/test/unit/**/*.spec.js',
'dist/templates/**/*.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
});
};
And my unit test looks like this:
describe('NavCtrl', function(){
var scope;
beforeEach(angular.mock.module('integra'));
beforeEach(angular.mock.inject(function($rootScope,$controller){
scope = $rootScope.$new();
$controller('NavCtrl', {$scope: scope});
}));
$scope.type = {
language: "English",
i18n: "en_EN"
};
$scope.option(type);
expect($scope.type.i18n).toEqual('en_EN');
})
This is the error:
Chrome 33.0.1750 (Linux) ERROR
Uncaught ReferenceError: $controller is not defined
at ~/Project/theApp/src/test/unit/app/navigation/NavCtrl.spec.js:2
Why isn't the $controller defined? Where should I define it? The controller I wan't to test is located in /src/js/navigation/NavCtrl.js
Error in path to controller's file in the configuration file.
Used
files: [
...,
'src/js/app/navigation/*js',
...
],
Instead of
files: [
...,
'src/js/app/navigation/*.js',
...
],
I'm working on an angular application that is written in CommonJS syntax and uses a grunt task with the grunt-contrib-requirejs task to translate the source files to AMD format and compile it into one output file. My goal is to make Karma work with RequireJS and keep my source files and spec files in CommonJS syntax.
I've been able to get a simple test passing in AMD format with the following file structure:
-- karma-test
|-- spec
| `-- exampleSpec.js
|-- src
| `-- example.js
|-- karma.conf.js
`-- test-main.js
and the following files:
karma.conf.js
// base path, that will be used to resolve files and exclude
basePath = '';
// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
REQUIRE,
REQUIRE_ADAPTER,
'test-main.js',
{pattern: 'src/*.js', included: false},
{pattern: 'spec/*.js', included: false}
];
// list of files to exclude
exclude = [];
// test results reporter to use
// possible values: 'dots', 'progress', 'junit'
reporters = ['progress'];
// web server port
port = 9876;
// cli runner port
runnerPort = 9100;
// enable / disable colors in the output (reporters and logs)
colors = true;
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_DEBUG;
// enable / disable watching file and executing tests whenever any file changes
autoWatch = true;
// Start these browsers, currently available:
browsers = ['Chrome'];
// 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 = false;
example.js
define('example', function() {
var message = "Hello!";
return {
message: message
};
});
exampleSpec.js
define(['example'], function(example) {
describe("Example", function() {
it("should have a message equal to 'Hello!'", function() {
expect(example.message).toBe('Hello!');
});
});
});
test-main.js
var tests = Object.keys(window.__karma__.files).filter(function (file) {
return /Spec\.js$/.test(file);
});
requirejs.config({
// Karma serves files from '/base'
baseUrl: '/base/src',
// Translate CommonJS to AMD
cjsTranslate: true,
// ask Require.js to load these files (all our tests)
deps: tests,
// start test run, once Require.js is done
callback: window.__karma__.start
});
However, my goal is to write both the source file and the spec file in CommonJS syntax with the same results, like so:
example.js
var message = "Hello!";
module.exports = {
message: message
};
exampleSpec.js
var example = require('example');
describe("Example", function() {
it("should have a message equal to 'Hello!'", function() {
expect(example.message).toBe('Hello!');
});
});
But despite having the cjsTranslate flag set to true, I just receive this error:
Uncaught Error: Module name "example" has not been loaded yet for context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded
at http://localhost:9876/adapter/lib/require.js?1371450058000:1746
Any ideas on how this can be accomplished?
Edit: I found this issue for the karma-runner repo: https://github.com/karma-runner/karma/issues/552 and there's a few comments that may help with this problem, but I haven't had any luck with them so far.
The solution I ended up finding involved using grunt and writing some custom grunt tasks. The process goes like this:
Create a grunt task to build a bootstrap requirejs file by finding all specs using a file pattern, looping through them and building out a traditional AMD style require block and creating a temporary file with code like this:
require(['spec/example1_spec.js'
,'spec/example2_spec.js',
,'spec/example3_spec.js'
],function(a1,a2){
// this space intentionally left blank
}, "", true);
Create a RequireJS grunt task that compiles the above bootstrap file and outputs a single js file that will effectively include all source code, specs, and libraries.
requirejs: {
tests: {
options: {
baseUrl: './test',
paths: {}, // paths object for libraries
shim: {}, // shim object for non-AMD libraries
// I pulled in almond using npm
name: '../node_modules/almond/almond.min',
// This is the file we created above
include: 'tmp/require-tests',
// This is the output file that we will serve to karma
out: 'test/tmp/tests.js',
optimize: 'none',
// This translates commonjs syntax to AMD require blocks
cjsTranslate: true
}
}
}
Create a grunt task that manually starts a karma server and serve the single compiled js file that we now have for testing.
Additionally, I was able to ditch the REQUIRE_ADAPTER in the karma.conf.js file and then only include the single compiled js file instead of the patterns that matched all source code and specs, so it looks like this now:
// base path, that will be used to resolve files and exclude
basePath = '';
// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
REQUIRE,
'tmp/tests.js'
];
// list of files to exclude
exclude = [];
// test results reporter to use
// possible values: 'dots', 'progress', 'junit'
reporters = ['progress'];
// web server port
port = 9876;
// cli runner port
runnerPort = 9100;
// enable / disable colors in the output (reporters and logs)
colors = true;
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_INFO;
// enable / disable watching file and executing tests whenever any file changes
autoWatch = true;
// Start these browsers, currently available:
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;
In the grunt task configuration for the requirejs compilation, it was also necessary to use almond in order to start the test execution (test execution would hang without it). You can see this used in the requirejs grunt task config above.
There's a couple things. First of all: I might have missed some details in your question (as it is super huge) - so sorry about that.
In short, you may want to checkout Backbone-Boilerplate wip branch testing organization: https://github.com/backbone-boilerplate/backbone-boilerplate/tree/wip
First: RequireJS does not support unwrapped raw common.js module. cjsTranslate is a R.js (the build tool) option to convert Commonjs to AMD compatible during build. As so, requiring a CJS raw module won't work. To resolve this issue, you can use a server to filter the scripts sent and compile them to AMD format. On BBB, we pass file through a static serve to compile them:
karma proxies setting: https://github.com/backbone-boilerplate/backbone-boilerplate/blob/wip/Gruntfile.js#L232-L234
Server setting: https://github.com/backbone-boilerplate/backbone-boilerplate/blob/wip/Gruntfile.js#L173-L179
Second: The Karma requirejs plugin isn't working super well - and it's somehow easy to use requireJS directly. On BBB, that's how we managed it: https://github.com/backbone-boilerplate/backbone-boilerplate/blob/wip/test/jasmine/test-runner.js#L16-L36
Hope this helps!