I have a stable product which uses angular 1.2.23. Of late, I decided to move to angular 1.4.3. After few compatibility issues with all the dependencies, my application is working fine, but all the unit testcases have started failing..After investing I realized that if I upgrade versions of all dependencies but keep angular at the previous version i.e 1.2.23, the testcases work fine..With angular 1.4.3, for some reason the injections of the dependencies in unit tests are failing.
Following is the list of the updated dependencies in bower.json.
"dependencies": {
"angular-cookies": "1.4.3",
"bootstrap": "3.0.3",
"angular-ui-router": "0.2.15",
"angular-gettext": "2.1.0",
"angular": "1.4.3",
"angular-ui-utils": "3.0.0",
"restangular": "1.4.0",
"angular-route": "1.4.3",
"momentjs": "2.10.6",
"angular-i18n": "1.4.3"
}
Following is the test file -
describe("Module: x.xyz", function () {
describe("Factory: xyz", function () {
var service;
beforeEach(function () {
module('x.xyz');
inject(function ($injector) {
service = $injector.get("xyz");
});
});
describe("Testing service(): ", function () {
describe('Testing getXYZDescription(): ', function () {
it('should return the description for the xyz event name passed if it is available', function () {
expect(service.getXYZDescription('abc')).toBe('abc');
});
});
});
});
});
When I run the above test case, I get service is undefined. Can anyone help?
I ran into a similar issue when upgrading from angular 1.3 to 1.4. In my case, I forgot to upgrade angular-mocks from 1.3 to 1.4. I suspect that mocking functionality was broken out into a separate module in the transition from 1.2 to 1.3, although I can't seem to find documentation to confirm that. In that case, you wouldn't have needed an angular-mocks dependency for your original app, but you would need to add the dependency when upgrading.
You should be able to fix this by adding "angular-mocks": "1.4.x" to your list of dependencies and a link to installed file in your karma config. For completeness, here's a minimal example:
karma.conf.js:
/*global module*/
module.exports = function (config) {
'use strict';
config.set({
basePath: '.',
frameworks: ['jasmine'],
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'*.js'
],
autoWatch: true,
singleRun: false,
browsers: ['Chrome']
});
};
package.json:
{
"name": "angular-inject-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "karma start karma.conf.js"
},
"author": "",
"dependencies": {
"angular": "1.4.x",
"angular-mocks": "1.4.x",
"karma": "^0.13.x",
"karma-cli": "^0.1.x",
"karma-jasmine": "^0.3.x",
"karma-chrome-launcher": "^0.2.x"
}
}
test.js:
/*global angular, beforeEach, describe, expect, inject, it, module*/
angular.module('x', [])
.factory('xyz', function () {
"use strict";
return {
getXYZDescription: function (value) {
return value;
}
};
});
describe("Module: x.xyz", function () {
"use strict";
describe("Factory: xyz", function () {
var service;
beforeEach(function () {
module('x');
inject(function ($injector) {
service = $injector.get("xyz");
});
});
it('Should echo input', function () {
expect(service.getXYZDescription('abc')).toBe('abc');
});
});
});
Related
This question already has an answer here:
Argument 'fn' is not a function, when trying to do unit test with Jasmine and AngularJS
(1 answer)
Closed 4 years ago.
Trying to load controller module in unit testing karma + jasmine + ionic Angular 1.5.3.
Module/Controller file
angular.module('App.View.Controllers', []).controller('ListController',
function($scope){
$scope._userName = UserService.getUserObject().maxperson;
});
describe("ListController", function(){
var $scope, $controller, ListController;
beforeEach(function () {
module('App.View.Controllers');
});
beforeEach(inject(function(_$rootScope_, _$controller_) {
$scope = $rootScope.$new();
$controller = _$controller_;
ListController = $controller('ListController', {$scope: $scope});
}));
it("has a dummy controller", function(){
expect(2+2).toEqual(4);
});
it('should be defined', function() {
expect(ListController).toBeDefined();
});
});
Gives me error:
Error: [$injector:modulerr] Failed to instantiate module App.View.Controllers due to:
Error: [$injector:nomod] Module 'App.View.Controllers' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.5.3/$injector/nomod?p0=App.View.Controllers
at node_modules/angular/angular.js:68:12
It is ionic app. Actually controller loads dependency also but for time sake I have commented it out to make a simple controller loads.
package.json file
{
"name": "karma-2174",
"version": "1.0.0",
"description": "",
"devDependencies": {
"#uirouter/angularjs": "^1.0.3",
"angular": "^1.5.3",
"angular-mocks": "^1.5.3",
"jasmine-core": "^2.0.4",
"karma": "^1.5.0",
"karma-chrome-launcher": "^2.0.0",
"karma-jasmine": "^1.1.0"
},
"scripts": {
"test": "karma start"
},
"author": "",
"license": "ISC"
}
Please check that you have added all the files in karma.conf.js and also take the example of this link:
In the case of ionic, you have added the main ionic file in karma.conf file
https://scotch.io/tutorials/testing-angularjs-with-jasmine-and-karma-part-1
I used (Yeoman) generator-cg-angular to scaffold my AngularJS web-app, and I'm trying to run unit tests without using the html2js preprocessor, but alas it looks like I'm missing something.
I changed the folders tree
As per customer request, I moved index.html, app.js and app.less within a folder named app, so now the folder structure is something like the following:
|--- Gruntfile.js //the Gruntfile.js is in the root folder, just like this generator does out-of-the-box
|___dist
|___unit-test-results
|___node_modules
|___bower_components
|___app
|____app.js
|____app.less
|____index.html
|____directives
|____test-directive
|____test-directive.js
|____test-directive.less
|____test-directive.html
|____test-directive-spec.js
My karma task
karma: {
options: {
frameworks: ['jasmine'],
files: [ //this files data is also updated in the watch handler, if updated change there too
'<%= dom_munger.data.appjs %>',
'bower_components/angular-mocks/angular-mocks.js',
'<%= ngtemplates.main.dest %>',
'directive/**/*.html',
createFolderGlobs('*-spec.js')
],
logLevel:'ERROR',
reporters:['mocha','html'],
autoWatch: false, //watching is handled by grunt-contrib-watch
singleRun: true,
htmlReporter: {
outputFile: 'unit-test-results/unit-tests'+ grunt.template.today('yyyymmdd') +'.html',
// Optional
pageTitle: 'Unit Tests',
groupSuites: true,
useCompactStyle: true
}
},
all_tests: {
browsers: ['Chrome','Firefox']
},
during_watch: {
browsers: ['PhantomJS']
},
},
The test-directive-spec.js
describe('testDirective', function() {
beforeEach(module('myApp'));
beforeEach(module('directive/test-directive/test-directive.html')); //manually written
var scope,compile;
beforeEach(inject(function($rootScope,$compile) {
scope = $rootScope.$new();
compile = $compile;
}));
it('should ...', function() {
var element = compile('<test-directive></test-directive>')(scope);
scope.$digest();
expect(element.text()).toBe('hello world');
});
});
grunt test fails
When I run grunt test configured like this
grunt.registerTask('test',['dom_munger:read','karma:all_tests']);
the html report file says he the tests failed because the templates were not found
Error: [$injector:modulerr] Failed to instantiate module directive/test-directive/test-directive.html due to:
Error: [$injector:nomod] Module 'directive/test-directive/test-directive.html' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
So I tried adding the ngtemplates task to grunt test like this
grunt.registerTask('test',['dom_munger:read','ngtemplates','karma:all_tests']);
configuring ngtemplates like this
ngtemplates: {
main: {
options: {
module: pkg.name,
htmlmin:'<%= htmlmin.main.options %>',
url: function(url){ return url.replace('app/','')}
},
src: [createFolderGlobs('*.html'),'!'+ indexHtmlPath +'index.html','!_SpecRunner.html'],
dest: 'temp/templates.js'
}
}
and produces the following templates.js in a temp folder
angular.module('myApp').run(['$templateCache', function($templateCache) {
'use strict';
$templateCache.put('directive/test-directive/test-directive.html',
"<div>hello world</div>"
);
}]);
But the html reporter still says that the templates are not found.
What am I doing so wrong?
Here's my package.json
{
"name": "myApp",
"version": "0.0.0",
"devDependencies": {
"eslint": "^3.16.1",
"eslint-config-angular": "^0.5.0",
"eslint-plugin-angular": "^1.6.1",
"grunt": "~0.4",
"grunt-angular-templates": "~0.5",
"grunt-browser-output": "0.1.0",
"grunt-contrib-clean": "~0.5",
"grunt-contrib-concat": "~0.3",
"grunt-contrib-connect": "~0.6",
"grunt-contrib-copy": "~0.5",
"grunt-contrib-cssmin": "~0.7",
"grunt-contrib-htmlmin": "~0.1",
"grunt-contrib-jshint": "~0.9",
"grunt-contrib-less": "~0.8",
"grunt-contrib-uglify": "~0.2",
"grunt-contrib-watch": "~0.6",
"grunt-dom-munger": "~3.4",
"grunt-file-exists": "^0.1.4",
"grunt-karma": "~0.8.3",
"grunt-ng-annotate": "^1.0.1",
"grunt-replace": "^1.0.1",
"grunt-timer": "^0.6.0",
"karma": "~0.12.6",
"karma-chrome-launcher": "~0.1.3",
"karma-firefox-launcher": "~0.1.3",
"karma-htmlfile-reporter": "^0.3.5",
"karma-jasmine": "~0.1.5",
"karma-mocha-reporter": "^2.2.2",
"karma-ng-html2js-preprocessor": "^1.0.0",
"karma-phantomjs-launcher": "~0.1.4",
"load-grunt-tasks": "~0.2"
}
}
After a lot of keyboard facerolling, I've come to this solution:
remove that directive/**/*.html from karma.options.files task configuration, since a) it's not enforcing project "folders-by-feature" structure and b) instead getting the templates from '<%= ngtemplates.main.dest %>' it's solid enough, you just need to change the grunt test task into grunt.registerTask('test',['dom_munger:read','ngtemplates','karma:all_tests']);
remove beforeEach(module('directive/test-directive/test-directive.html')); from test-directive-spec.js, since it looks like it clashes with the previously described ngtemplates mechanism, making the template unavaiable;
Using the angular.mock.inject(...) function when trying to unit test an Angular (Ionic) 1 application throws the following error. The strange thing is that there is no specific error message, making particularly hard to debug. No matter what I try, it always seems to throw this same non-descript error without any message.
PhantomJS 2.1.1 (Linux 0.0.0) LoginController should pass FAILED
bower_components/angular/angular.js:4527:53
forEach#bower_components/angular/angular.js:321:24
loadModules#bower_components/angular/angular.js:4487:12
createInjector#bower_components/angular/angular.js:4409:30
WorkFn#bower_components/angular-mocks/angular-mocks.js:3160:60
loaded#http://localhost:9876/context.js:151:17
Removing the call to angular.mock.inject() allows the test to pass.
Here's the test in question:
describe('LoginController', function() {
var scope;
var controller;
beforeEach(angular.mock.module('mCommonJobs'));
beforeEach(angular.mock.inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('LoginController', {
$scope: scope
});
}));
it('should pass', function() {
expect(true).toEqual(true);
});
});
My bower dependencies:
"dependencies": {
"angular-resource": "#1.5.0",
"ionic": "driftyco/ionic-bower#1.3.2",
"ngCordova": "^0.1.27-alpha",
"ng-cordova-oauth": "^0.3.0",
"ngstorage": "^0.3.11",
"angular-mocks": "^1.5.2"
},
"resolutions": {
"angular": "~1.5.x"
}
And the files set in the Karma test config:
files: [
//Angular source
'bower_components/angular/angular.js',
'bower_components/angular-animate/angular-animate.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/angular-resource/angular-resource.js',
'bower_components/angular-sanitize/angular-sanitize.js',
'bower_components/angular-ui-router/release/angular-ui-router.js',
'bower_components/ionic/js/ionic.bundle.js',
'bower_components/ng-cordova-oauth/dist/ng-cordova-oauth.js',
'bower_components/ngCordova/dist/ng-cordova.js',
'bower_components/ngCordova/dist/ng-cordova-mocks.js',
'bower_components/ngstorage/ngStorage.js',
//App code
'app/**/*.module.js',
'app/**/*.js',
'app/*.js',
//Test files
'test/**/*.test.js'
],
This issue was resolved by not including all of ionic.bundle.js in the files config of karma, but by specifically including its parts.
I also explicitly forced all versions of angular-related dependencies to be the same version (special thanks to Phil in the comments.).
In the end, my bower.json had:
"dependencies": {
"angular-resource": "1.5.2",
"ionic": "driftyco/ionic-bower#1.3.2",
"ngCordova": "^0.1.27-alpha",
"ng-cordova-oauth": "^0.3.0",
"ngstorage": "^0.3.11",
"angular-mocks": "1.5.2"
},
and my karma config looked like:
files: [
//Angular source
'bower_components/angular/angular.js',
'bower_components/angular-animate/angular-animate.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/angular-resource/angular-resource.js',
'bower_components/angular-sanitize/angular-sanitize.js',
'bower_components/angular-ui-router/release/angular-ui-router.js',
'bower_components/ionic/js/ionic.js',
'bower_components/ionic/js/ionic-angular.js',
'bower_components/ng-cordova-oauth/dist/ng-cordova-oauth.js',
'bower_components/ngCordova/dist/ng-cordova.js',
'bower_components/ngCordova/dist/ng-cordova-mocks.js',
'bower_components/ngstorage/ngStorage.js',
//App code
'app/**/*.module.js',
'app/**/*.js',
'app/*.js',
//Test files
'test/**/*.test.js'
],
Im facing a problem when I try to use browserify, angularjs and restangular.
When I try to require the npm or bower module, for example require('restangular), browserify returns empty object. This happens when i require any bower or npm modules. When I try to require any local file, everything is working fine.
file structure:
bower_components/
src/
-client
-app
app.js
backend
backend.module.js
-test
test.module.ls
test.js
node_modules/
app.js
(function() {
'use strict';
require('angular');
var rest = require('restangular');
console.log(rest);
module.exports = angular
.module('app', [
require('restangular').name,
require('./test/test.module').name,
]);
})();
package.json
"browserify": {
"transform": [
"browserify-shim"
]
},
"browser": {
"restangular": "./bower_components/restangular/dist/restangular.js"
},
"browserify-shim": {
"restangular": "restangular"
}
gulpfile.js
gulp.task('browserify', function() {
gulp.src(['./src/client/app/app.js'])
.pipe(plugins.browserify({
insertGlobals: true,
debug: true
}))
.pipe(plugins.concat('bundled.js'))
.pipe(gulp.dest('./src/client/js'))
});
Can you help me?
Thanks in advance.
Just modify your "browser" part in package.json:
"browserify-shim": {
"angular": {
"exports": "angular"
},
"restangular": {
"depends": [
"angular"
],
"exports": "restangular"
}
}
Hope it will work.
Try modifying your package.json file with this snippet.
"browser": {
"restangular": "./bower_components/restangular/dist/restangular.js"
},
"browserify-shim": {
"restangular": {
"depends": [
"angular",
"lodash:_"
],
"exports": "null"
}
}
Solution courtesy of #newtricks from this discussion
I am trying to run karma unit tests for my application. The application is created using my company's custom angular yeoman generator. (The generator is very similar to the angular-yeoman generator).
I am trying to run karma jasmine test for my application. But I keep on getting the error message whenever I run grunt test
Chrome 35.0.1916 (Mac OS X 10.9.0) ERROR Uncaught object at
/Users//Dummy
Apps/karma1/app/bower_components/angular/angular.js:1611
Warning: Task "karma:unit" failed. Use --force to continue.
I have the following in my Gruntfile.js:
karma: {
unit: {
configFile: 'karma.conf.js',
singleRun: true
}
}
In karma.conf.js file I have :
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',
'app/bower_components/angular-bootstrap/ui-bootstrap.js',
'app/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
'app/bower_components/service-state/js/StateService.js',
'app/scripts/controllers/dashboard.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
});
};
My package.json file :
{
"name": "karma1",
"version": "0.0.0",
"dependencies": {},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-css": "~0.5.4",
"grunt-contrib-copy": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-coffee": "~0.7.0",
"grunt-contrib-uglify": "~0.2.0",
"grunt-contrib-compass": "~0.5.0",
"grunt-contrib-jshint": "~0.6.0",
"grunt-contrib-less": "~0.9.0",
"grunt-contrib-cssmin": "~0.6.0",
"grunt-contrib-connect": "~0.5.0",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-htmlmin": "~0.1.3",
"grunt-contrib-watch": "~0.5.2",
"grunt-autoprefixer": "~0.2.0",
"grunt-usemin": "~0.1.11",
"grunt-rev": "~0.1.0",
"grunt-shell": "~0.2.2",
"grunt-concurrent": "~0.3.0",
"load-grunt-tasks": "~0.1.0",
"grunt-google-cdn": "~0.2.0",
"grunt-ngmin": "~0.0.2",
"time-grunt": "~0.1.0",
"karma-ng-scenario": "^0.1.0",
"grunt-karma": "^0.8.3",
"karma": "^0.12.16",
"karma-ng-html2js-preprocessor": "^0.1.0",
"karma-jasmine": "^0.1.5",
"karma-chrome-launcher": "^0.1.4",
"karma-mocha": "latest",
"chai": "1.4.0",
"karma-script-launcher": "~0.1.0",
"karma-html2js-preprocessor": "~0.1.0",
"karma-requirejs": "~0.2.0",
"karma-coffee-preprocessor": "~0.1.0",
"karma-phantomjs-launcher": "~0.1.0",
"grunt-open": "~0.2.2",
"ng-midway-tester": "2.0.5"
},
"engines": {
"node": ">=0.8.0"
},
"scripts": {
"test": "grunt test"
}
}
My test controller is :
'use strict';
describe('Controller: DashboardCtrl', function () {
// load the controller's module
beforeEach(module('karma1App'));
var DashboardCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller,$rootScope) {
scope = $rootScope.$new();
DashboardCtrl = $controller('DashboardCtrl', {
$scope: scope
});
}));
it('should attach a list of awesomeThings to the scope', function () {
expect(scope.awesomeThings.length).toBe(3);
});
});
I use REQUIREJS to load the other dependencies, but REQUIRE is used only in the directives. As a kick start I want to test my controllers and services but I keep getting this error.
Any idea what is going wrong.
Thanks!
The point I was missing that I was not loading the angular app. I am loading the angular app through a config file config.js
/* global angular */
'use strict';
var karma1App = angular.module('karma1App', [
'pascalprecht.translate', 'ngResource', 'ngRoute',
'ui.bootstrap' ]);
karma1App.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/site', {
activeTabName: 'site',
templateUrl: 'views/site.html',
controller: 'SiteCtrl'
})
.when('/Cases', {
templateUrl: 'views/Cases.html',
controller: 'CasesCtrl'
})
.when('/Cases/:caseid', {
templateUrl: 'views/Case.html',
controller: 'CaseCtrl'
})
.when('/Alarms', {
templateUrl: 'views/Alarms.html',
controller: 'AlarmsCtrl'
})
.when('/Analysis', {
templateUrl: 'views/Analysis.html',
controller: 'AnalysisCtrl'
})
.when('/Reports', {
templateUrl: 'views/Reports.html',
controller: 'ReportsCtrl'
}) /*
.when('/dashboard', {
activeTabName: 'dashboard',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
*/
.when('/admin', {
templateUrl: 'views/admin.html',
controller: 'AdminCtrl'
})
.otherwise({
redirectTo: '/site'
}); }]);
In the karma.conf.js I added this following script tag :
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',
'app/bower_components/angular-bootstrap/ui-bootstrap.js',
'app/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
'./test/test-main.js',
'app/scripts/controllers/dashboard.js',
'../test/spec/**/*.js'
]
The test-main.js has the following line of code ONLY:
/* global angular */
'use strict';
var karma1App = angular.module('karma1App', [
'ngResource',
'ngRoute', // Angular 1.2 requires separate ngRoute
'ui.bootstrap',
'StateService'
]);
After loading the test-main.js file in the karma.conf.js file I was able to unit test my application using karma.
Hope this helps.
Thanks,
Anirban