I'm actually stuck since few hours, my boss wants me to proceed to unit testing on the functionalities i coded last week, when I do my karma start karma.conf.js it gives me the following issue :
"message": "An error was thrown in afterAll\nUncaught ReferenceError: angular is not defined",
my files structure :
webapp
-www
-services
api.service.js
-test
test.test.js
karma.conf.js
essential of karma.conf.js :
module.exports = function(config) {
config.set({
files: [
'www/js/services/api.service.js',
'test/**/*.test.js'
],
})
}
I think Karma doesn't find my api.service.js but i don't know why, the angularjs code actually work in the webapp.
content of my test.test.js :
(function() {
'use strict';
describe('apiService', function() {
it('should return an array of object', function() {
var artist = typeof getArtist(118680); // MGMT Artist
console.log(artist);
expect(artist).toEqual('array');
});
});
})();
getArtist is the function I need to test situated in api.service.js.
Thank you,
Paul.
Karma needs the angular file to test angularJS code. You need to include it in the files array in the karma configuration.
module.exports = function(config) {
config.set({
files: [
'path-to-angular.js',
'www/js/services/api.service.js',
'test/**/*.test.js'
],
})
}
Related
I am new to Jasmine and Karma testing.
I am trying to Unit test AngularJs Service.
While writing Specs, I came around two types of Code for injecting Module.
1st Type
beforeEach(angular.mock.module("app"));
2nd Type
beforeEach(function () {
angular.module("app");
});
Can anybody explain the difference between the above two in simple plain English with a simple example.
And also, which code to use in what kind of scenario?
I tried to Google it, but was not able to find a proper answer.
Thanks :)
From angular-mocks.js
window.module = angular.mock.module = function() {
...
More info:
http://www.bradoncode.com/blog/2015/05/24/ngmock-fundamentals-angularjs-unit-testing/
https://github.com/bbraithwaite/angular.js/blob/master/src/ngMock/angular-mocks.js#L2259
https://gist.github.com/trinitroglycerin/68754b920df83a977f12#gistcomment-2851474
To enable usage of 'module' add this to webpack configuration:
const webpack = require('webpack');
module.exports = function(config) {
config.set({
//...config
webpack: {
//...webpack config
plugins: [
new webpack.DefinePlugin({
module: 'window.module',
}),
],
}
});
};
I've tried several tutorials and looked at many of the solutions provided here. I am new to Angular and currently trying to set up testing for a rather big SPA.
Following this tutorial I have completed:
Angularjs application setup
Karma setup
Our first test
The karma config file is basically the default content, with some references in files and exclude:
// list of files/patterns to load in the browser
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'app/app.js',
'JavaScript.spec.js'
],
I reinstalled the entire test implementation and now the simple test works again. But trying to write a test for a controller does not work:
here is the error message
I changed the path referencing the bower_components and app files in the karma config file. Now the shell running karma returns an error message from the app.js file, saying:
Uncaught ReferenceError: Logging is not defined
Writing a test identical to the one from doucmentation, gives the following error:
Here is the test code:
describe('nyKladdController', function () {
beforeEach(module('app'));
var $controller;
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
describe('$scope.mixTable', function () {
it('is false', function () {
var $scope = {};
var controller = $controller('nyKladdController', { $scope: $scope });
expect($scope.mixTable).toBeFalsy();
});
});
});
As you can see from the error message: after the app module, the test file start loading the app dependencies. Here is the app.js file:
(function () {
'use strict';
angular.module('app', [
'ngAnimate', 'ngRoute', 'ngSanitize', 'ngResource', 'ngMessages',
'AdalAngular', 'config', 'angular.filter',
'ui.bootstrap', 'ui.mask', 'ui.select', 'ui.validate',
'angular-loading-bar', 'ui.tree', 'ui.tree-filter', 'checklist-model'
]);
})();
In other words: how can i get my tests to load the app dependecies as well.
I had to load in all the app dependencies from app.js in to karma.config file. Now the files array in karma config looks like this:
// list of files / patterns to load in the browser
files: [
//bower modules
'./bower_components/angular/angular.js',
'./bower_components/angular-mocks/angular-mocks.js',
'./bower_components/angular-ui-mask/src/mask.js',
'./bower_components/angular-ui-select/dist/select.js',
'./bower_components/angular-ui-tree-filter/dist/angular-ui-tree-filter.js',
'./bower_components/angular-ui-tree/dist/angular-ui-tree.js',
'./bower_components/angular-ui-validate/dist/validate.js',
'./bower_components/angular-loading-bar/build/loading-bar.js',
// node modules
'./node_modules/angular-animate/angular-animate.js',
'./node_modules/angular-route/angular-route.js',
'./node_modules/angular-sanitize/angular-sanitize.js',
'./node_modules/angular-resource/angular-resource.js',
'./node_modules/angular-messages/angular-messages.js',
'./node_modules/adal-angular/dist/adal-angular.min.js',
'./node_modules/angular-filter/dist/angular-filter.js',
'./node_modules/angular-ui-bootstrap/dist/ui-bootstrap.js',
'./node_modules/bower-config/lib/Config.js',
'./node_modules/checklist-model/checklist-model.js',
//app file
'./app/app.js',
'./app/common/config/config.js',
//test files etc..
'JavaScript.spec.js',
'./app/produkt/ny/controllers/*.js' // tester å hente inn controller som refereres i test filen
],
This may be because Karma is loading the source files in the wrong order. For Angular to work properly, each module must be loaded before any component, services, etc. associated with that module.
To fix this, you can change your Karma configuration to ensure your module files are loaded first.
// list of files / patterns to load in the browser
files: [
'../../bower_components/angular/angular.js',
'../../bower_components/angular-mocks/angular-mocks.js',
'app/**/*.module.js',
'app/**/*.js'
],
This is assuming you're using some kind of naming convention for angular modules (like *.module.js as in the above example). Otherwise you'll have to list the paths to the modules individually.
add beforeEach(module("your-module-name")); => your angular application name from app.js"
describe('check a controller', function () {
beforeEach(module("your module name")); // I think you missed this.
var scope, checkController;
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.new();
checkController = function () {
return $controller('nyKladdController', {
'$scope': scope
});
};
}));
it('has a dummy spec to test 2 + 2', function () {
// An intentionally failing test. No code within expect() will never equal 4.
expect(2 + 2).toEqual(4);
});
});
karma.conf
files: [ // sample order. Include your files accordingly
'src/bower_components/angular/angular.min.js',
'src/bower_components/angular-mocks/angular-mocks.js',
// some sample libraries
'src/bower_components/angular-cookies/angular-cookies.min.js',
'src/bower_components/angular-ui-router/release/angular-ui-router.min.js',
'src/bower_components/angular-resource/angular-resource.min.js',
'src/bower_components/angular-sanitize/angular-sanitize.min.js',
'src/bower_components/angular-loading-bar/build/loading-bar.min.js',
'src/app/app.js',
'src/app/**/*.js',
'tests/unit/**/*.spec.js'
],
exclude: []
Testing my angular app with karma ngHtml2JsPreprocessor, I have read dozens of pages on how ton configure karma to generate js templates instead of html ones that are loaded by Angular Directives, I am stuck with the message :
Module 'js_templates' 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.4.6/$injector/nomod?p0=js_templates
My folder structure is like this :
/System/Root/Path/
web/
js/
app/
test/
specs/
UserModule/
UserDirectives.spec.js
modules/
UserModule/
UserDirectives.js <=== Where the directive is defined
Templates
login.tpl.html
My directive is defined like this :
directives.directive("loginForm", [function(){
return{
restriction: "E",
templateUrl: assetsRootPath+'/Templates/login.tpl.html' //assetsRootPath is defined to '' for karma
}]);
Karma is configured as follow :
module.exports = function(config) {
config.set({
basePath: './web/js/',
frameworks: ['jasmine', 'requirejs'],
preprocessors: {
'../Templates/**/*.html': ['ng-html2js']
},
ngHtml2JsPreprocessor: {
stripPrefix: '.*web/',
prependPrefix: '/',
moduleName: 'js_templates',
enableRequireJs: false
},
plugins : [
'karma-chrome-launcher',
'karma-jasmine',
'karma-requirejs',
'karma-ng-html2js-preprocessor'
],
// list of files / patterns to load in the browser
files: [
{ pattern: '../Templates/**/*.html', included: false },
//....Other needed files
]
The spec for testing the directive :
define(['angular', 'ngmocks', 'app/modules/UserModule/UserDirectives'], function() {
describe("Test User Directive > ", function () {
var $compiler, compiledElement;
beforeEach(module('User.Directives'));
beforeEach(module('js_templates'));
beforeEach(inject(function (_$rootScope_, _$compile_) {
$rootScope = _$rootScope_;
$compile = _$compile_;
scope = $rootScope.$new();
compiledElement = $compile("<login-form></login-form>")(scope);
scope.$digest();
}));
it('Tries to test', function(){
expect(1).toEqual(1);
});
});
});
When I launch the tests the following error appears :
Module 'js_templates' 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.4.6/$injector/nomod?p0=js_templates
I have tried a lot of configurations and nothing works, I have also tried to debug ngHtml2JsPreprocessor by adding some log.debug & I see that the module 'js_templates' is rightly created, the problem is why can't I load it for the specs. Information that could be useful (not sure if it changes something) : I am working with requirejs.
Thanks for your help
Well, as no config worked, I have chosen to use a different approach, below is what I ended up to do to make it work :
1 - Remove all pre-processors
2 - Install the simple html2js node plugin : npm install karma-html2js-preprocessor --save-dev
3 - Inside my karma.conf file :
pattern: { files: '../Templates/**/*.html', included : true } //Note the included property to true
preprocessors: {
'../Templates/**/*.html': ['html2js']
},
plugins : [
'karma-chrome-launcher',
'karma-jasmine',
'karma-requirejs',
'karma-html2js-preprocessor'
],
Inside my test-main.js file which is the entry point of require-js I have done this :
require([
'angular',
...
], function(angular, app) {
var $html = angular.element(document.getElementsByTagName('html')[0]);
angular.element().ready(function() {
// bootstrap the app manually
angular.bootstrap(document, ['app']);
//Making all templates to be availabe through js_template module
angular.module('js_templates', []).run(function($templateCache){
angular.forEach(window.__html__, function(content, filename){
var modifiedFilename = filename;
/*****************Modify this to fit your app**********************/
var breakPos = modifiedFilename.indexOf('/Templates');
modifiedFilename = filename.substr(breakPos, modifiedFilename.length - breakPos);
/*****************/Modify this to fit your app*********************/
$templateCache.put(modifiedFilename, content);
});
});
});
}
);
Not very sharp but not so bad as well, anyway it does work and it's exactly what I wanted. When a solution will come to work naturally with ngHtml2JsPreprocessor, I will use it.
I have Done a Library Management App with Angular JS and Mongo Lab will Act as a DB Part, I am facing issuse with Require JS Dependency While Crating Unit test Case
Error: [$injector:modulerr] Failed to instantiate module lmaApp due to:
Error: [$injector:nomod] Module 'lmaApp' is not available!
The Above error I am facing,kindly help me to get out from this.
MyCode:
Controller.js
define(
['modules'],
function(lmaApp) {
lmaApp.controller('gridControl',['$scope' , '$http' , 'internal' , 'commonValues', function($scope , $http , internalFn , commonValues){
jQuery('ul.navbar-nav li').removeClass('active');
jQuery('ul.navbar-nav li:nth-child(1)').addClass('active');
$('.loaderImg').removeClass('no-loading');
var lmaTableData = internalFn.getTableData(commonValues.mongoAPIurl,commonValues.bookTableName,'');
var promise = lmaTableData
.success(function(tbData) {
if(tbData.length > 0){
$scope.nobook=0;
$scope.books =tbData;
}
else{
$scope.nobook =1;
}
}).then(function (response) {$('.loaderImg').addClass('no-loading');});
}]);
});
modules.js
define(
['app_config','angularRoute'],
function() {
var lmaApp =angular.module('lmaApp',['ngRoute'])
return lmaApp;
});
app_config.js
define(
['angular','angularRoute','modules'],
function() {
angular.element(document).ready(function() {
angular.bootstrap(document, ['lmaApp'], {});
});
});
My spec File
controllerSpec.js
define(['angular', 'angular-mocks'], function() {
describe('gridControl', function(){
beforeEach(module('lmaApp'));
it('should get the book table Datas', inject(function($controller) {
var scope = {},
ctrl = $controller('gridControl', {$scope:scope});
expect(scope.phones.length).not.toEqual(0);
}));
});
});
Here i have a doubt with require js dependecy like i have to mention modules.js as a dependency in Spec file too.
Your controller-spec.js is wrong, you need to call its dependencies which is your module.js, app_config.js, Controller.js also 'angularRoute'. In other ot make your app to able to boostrap.
try it like this
define(['angular', 'angular-mocks','modules', 'app_config', 'Controller', 'angularRoute'], function() { ... }
Still I have nothing to be sure that it will work for you. Because if any of your configuration is wrong. It will be broken. Using requireJS with AngularJS in unit testing is very tricky/complex in the configuration.
You should read more about requireJS config, and using shim for define dependencies for your script. It will be lots clearer and eaiser to handle when your app getting bigger. For example you can do something like this in your config file:
shim: {
'modules': ['angular', 'app_config', 'angular-mocks'],
'app_config': ['angular', 'angularRoute', 'modules'],
'Controller': ['modules']
}
and your controller-spec.js will be like this
define(['modules', 'app_config', 'Controller'], function(){ ... });
Also Bootstraping angular on element ready is not a good idea for testing. It may cause some conflict in loading simulating of karma. I am not sure but don't feel right about it
Sencond Your app_config.js and modules.js are dependency of each other. So what do you think if there's something require an order in loading. Which will need to load first? since Both required the other to be loaded before it got to be injeacted by requireJS.
Still I don't think my solution will work. Because your config seem so wrong.
I have a problem to run my tests in Webstorm 8, here is my conf file :
Here is my AngularJS controller :
angular.module('monApp').controller('DashboardCtrl', [
'$scope', function ($scope) {
'use strict';
$scope.foo = 'bar';
}
]);
And my test file :
describe('Controller: DashboardCtrl', function () {
'use strict';
var DashboardCtrl,
scope;
beforeEach(module('monApp'));
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
DashboardCtrl = $controller('DashboardCtrl', {
$scope : scope
});
}));
it('dashboard should be defined', function () {
expect(scope.foo).toBeDefined();
expect(scope.foo).toBe('bar');
});
});
These are very simple, I followed steps of many tutorials, first installed node, then install karma with npm install, and when i run karma with karma start my.conf.js the test pass but it shows Empty test suite.
I precise that in my project, I just have 5 files :
angular.js
angular-mocks.js
the controller
test file
conf file
In the config file, i have added these 4 files with :
// list of files / patterns to load in the browser
files: [
'angular.js',
'angular-mocks.js',
'*.js'
],
When I try to throw the test by right-click I get an error telling : describe is not defined.
Thanks.
I tried to restart from scratch and it appears that my instantiation of my app module wasn't fine, this is better :
var app = angular.module('monApp', []);
app.controller('DashboardCtrl', ['$scope', function ($scope) { ....
And the first problem "empty test suite" was due to wrong basePath in the config file. Anyway, thanks for your answers !
Your my.conf.js must contain :
frameworks: ['jasmine']
And Karma need the bridge to Jasmine framework to be installed :
npm install karma-jasmine --save-dev
By default, karma loads all installed plugins which are starting with "karma-".