I copied the angularjs example for unit testing from here. As its just direct implementation of the example, i am confused with the error thrown.
I work in Linux and using Brackets to as IDE.
Please let know what is the missing element to run the jasmine tests.
Ouput of Jasmine
PasswordController encountered a declaration exception.
ReferenceError: module is not defined
controller.js
angular.module('app', [])
.controller('PasswordController', function PasswordController($scope) {
$scope.password = '';
$scope.grade = function() {
var size = $scope.password.length;
if (size > 8) {
$scope.strength = 'strong';
} else if (size > 3) {
$scope.strength = 'medium';
} else {
$scope.strength = 'weak';
}
};
});
controller-spec.js
describe('PasswordController', function() {
beforeEach(module('app'));
var $controller;
beforeEach(inject(function(_$controller_){
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
}));
describe('$scope.grade', function() {
it('sets the strength to "strong" if the password length is >8 chars', function() {
var $scope = {};
var controller = $controller('PasswordController', { $scope: $scope });
$scope.password = 'longerthaneightchars';
$scope.grade();
expect($scope.strength).toEqual('strong');
});
});
});
karma-conf.js
// list of files / patterns to load in the browser
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'bower_components/angular-resource/angular-resource.js',
'app/controllers/*.js',
'test/controllers/*.js'
],
Karma Output
/var/www/html/angular-jasmine-testing $ kma start karma.conf.js
INFO [karma]: Karma v0.12.31 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 41.0.2272 (Linux)]: Connected on socket vZCR4hAC8uU7LutFNVl3 with id 44440115
Chrome 41.0.2272 (Linux): Executed 1 of 1 SUCCESS (0.042 secs / 0.035 secs)
I managed to get your test working. See the plunkr below:
describe("PasswordController", function() {
beforeEach(module('app'));
var $scope = null;
beforeEach(inject(function($rootScope, $controller) {
$scope = $rootScope.$new();
$controller('PasswordController', {
$scope: $scope
});
}));
describe("$scope.grade", function() {
it("sets the strength to 'strong' if the password length is >8 chars", function() {
$scope.password = "longerthaneightchars";
$scope.grade();
expect($scope.strength).toEqual("strong");
});
})
});
plunkr
Related
I have the following unit test code in which first test is passing, but the second one is failing and I am not able to figure it out.
Unit test code
describe('List controller', function () {
beforeEach(angular.mock.module('myApp'));
var $controller, $rootScope, $scope, $state;
beforeEach(inject(function (_$controller_, _$rootScope_) {
$controller = _$controller_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
}));
describe('Parameter Group List', function() {
it('should exists', function () {
$controller = $controller('baseController', {'$scope': $scope});
expect($scope.prepareSidebarMenu).toBeDefined();
});
it('should exists', function () {
$state = {};
$scope.header = {};
$state.current = {};
var parameterGroups = '';
$scope.header.title = '';
$controller = $controller('listController', {'$scope': $scope, 'parameterGroups': parameterGroups });
expect($scope.truncateCharacters).toBeDefined();
});
});
});
and I am trying to test following controllers.
Base controller
(function () {
'use strict';
angular.module('PpmApp')
.controller('baseController', ['$scope', '$injector', baseController]);
function baseController($scope, $injector) {
var $state = $injector.get('$state');
$scope.header = {
title: "Plan Parameter Manager"
};
$scope.sidebarMenuInfo = {
name: $state.current.name,
parameterGroupId: null,
hideSidebar: true
};
$scope.prepareSidebarMenu = function (sidebarMenuInfo) {
angular.extend($scope.sidebarMenuInfo, sidebarMenuInfo);
};
}
})();
List controller
(function () {
'use strict';
angular.module('PpmApp')
.controller('listController', ['$scope', '$injector', 'parameterGroups', listController]);
function listController($scope, $injector, parameterGroups) {
var $state = $injector.get('$state');
var apiService = $injector.get('apiService');
var utilService = $injector.get('utilService');
var constantsProvider = $injector.get('constantsProvider');
$scope.header.title = "Parameter Manager Overview";
$scope.prepareSidebarMenu({
name: $state.current.name,
hideSidebar: true
});
var titleMaxLength = 47;
var descriptionMaxLength = 270;
$scope.parameterGroups = parameterGroups;
$scope.createPopupInfo = {};
$scope.createPopupInfo.validationErrors = {};
$scope.createPopupInfo.validationErrors.isError = false;
$scope.createPopupInfo.years = utilService.populateYearsForParameterGroup();
$scope.createPopupInfo.months = constantsProvider.months;
$scope.truncateCharacters = function (text, type) {
if (type == 'title' && text.length > titleMaxLength) {
return text.substring(0, titleMaxLength) + '...';
} else if (type == 'description' && text.length > descriptionMaxLength) {
return text.substring(0, descriptionMaxLength) + '...';
}
return text;
};
}
})();
My Unit test result is
$ karma start
07 02 2018 12:41:00.734:WARN [karma]: No captured browser, open http://localhost :9876/
07 02 2018 12:41:00.746:INFO [karma]: Karma v0.13.22 server started at http://lo calhost:9876/
07 02 2018 12:41:00.751:INFO [launcher]: Starting browser Chrome
07 02 2018 12:41:02.946:INFO [Chrome 63.0.3239 (Windows 7 0.0.0)]: Connected on socket doxoZRvKoJYdYozhAAAA with id 67949004
parameterGroupListController
Parameter Group List
√should exists
×should exists
TypeError: $scope.prepareSidebarMenu is not a function
at new parameterGroupListController (C:/ZS/JIM-PPM/PlanManagerWeb/Ji mPPM/app/controllers/parameter-group-list.js:14:16)
at Object.instantiate (C:/ZS/JIM-PPM/PlanManagerWeb/JimPPM/resources /angular.js:5112:14)
at $controller (C:/ZS/JIM-PPM/PlanManagerWeb/JimPPM/resources/angula r.js:11083:28)
at C:/ZS/JIM-PPM/PlanManagerWeb/JimPPM/node_modules/angular-mocks/an gular-mocks.js:2314:14
at UserContext.<anonymous> (C:/ZS/JIM-PPM/PlanManagerWeb/JimPPM/test s/parameter-group.spec.js:24:27)
Chrome 63.0.3239 (Windows 7 0.0.0): Executed 2 of 2 (1 FAILED) (0.038 secs / 0 s ecs)
TOTAL: 1 FAILED, 1 SUCCESS
1) should exists
parameterGroupListController Parameter Group List
TypeError: $scope.prepareSidebarMenu is not a function
at new parameterGroupListController (C:/ZS/JIM-PPM/PlanManagerWeb/JimPPM/app /controllers/parameter-group-list.js:14:16)
at Object.instantiate (C:/ZS/JIM-PPM/PlanManagerWeb/JimPPM/resources/angular .js:5112:14)
at $controller (C:/ZS/JIM-PPM/PlanManagerWeb/JimPPM/resources/angular.js:110 83:28)
at C:/ZS/JIM-PPM/PlanManagerWeb/JimPPM/node_modules/angular-mocks/angular-mo cks.js:2314:14
at UserContext.<anonymous> (C:/ZS/JIM-PPM/PlanManagerWeb/JimPPM/tests/parame ter-group.spec.js:24:27)
listController expects that prepareSidebarMenu is defined on scope, and it's not. If it is supposed to be defined by baseController and inherited from parent scope, it should be stubbed in listController test:
$scope.prepareSidebarMenu = jasmine.createSpy();
$controller = $controller('listController', {'$scope': $scope, 'parameterGroups': parameterGroups });
expect($scope.prepareSidebarMenu).toHaveBeenCalledWith(...);
expect($scope.truncateCharacters).toBeDefined();
This is my AngularJS code:
angular.module('myapp', [])
.controller('MainCtrl', function($scope, $http, $rootScope, $routeParams) {
$scope.name = "Girish";
$scope.sayHello = function() {
$scope.greeting = "Hello " + $scope.name;
};
$scope.commonUrl = "/";
$rootScope.$watch('eng', function() {
$scope.currentLang = $rootScope.CURRENT_LANGUAGE;
});
$scope.homePageFirstSlider = function() {
$scope.anun = "Nar";
$http({
method: 'GET',
url: "/" + "eng" + '/api/getslideritems/main'
}).then(function successCallback(response) {
$scope.Data = response.data;
$scope.loadCss('mainCarousel');
},
function errorCallback(response) {});
};
});
This is a test file:
'use strict';
describe('myapp', function() {
beforeEach(module('myapp'));
var $controller;
beforeEach(inject(function(_$controller_) {
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
}));
describe('$scope.sayHello', function() {
it('same tests', function() {
var $scope = {};
var controller = $controller('MainCtrl', { $scope: $scope });
$scope.name = 'Girish';
$scope.sayHello();
expect($scope.greeting).toEqual('Hello Girish');
});
});
});
After I run karma.conf.js file I have this error:
PhantomJS 2.1.1 (Linux 0.0.0) myapp $scope.sayHello same tests FAILED
***Error: [$injector:unpr] Unknown provider: $routeParamsProvider <- $routeParams <- MainCtrl***
http://errors.angularjs.org/1.5.0/$injector/unpr?p0=%24routeParamsProvider%20%3C-%20%24routeParams%20%3C-%20MainCtrl in /var/www/html/famboxv2/public/bower_components/angular/angular.js (line 4397)
loaded#http://localhost:9882/context.js:151:17
PhantomJS 2.1.1 (Linux 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.025 secs / 0.004 secs)
Chromium 45.0.2454 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.008 secs / 0.005 secs)
How can I solve this error?
Unknown provider: $routeParamsProvider <- $routeParams <- MainCtrl
$routeParams service is a part of ngRoute module. So you'll have to include it as a dependency on your module.
Here's how:
angular.module('myapp', ['ngRoute'])
Also you should be mocking the controller in the first beforeEach block instead of mocking it inside a specific test, so that it could be reusable in all your tests.
And your tests will still be failing because you've inject an empty object for $scope instead of creating a new scope using the $rootScope's $new function. So you should be doing the following changes to make them pass:
describe('myapp', function() {
beforeEach(module('myapp'));
//Replace this
beforeEach(inject(function($controller, _$rootScope_){
//With this
// beforeEach(inject(function($controller, _$rootScope_, _$routeParams_, _$http_){
//Uncomment the following comments if needed for writing tests for the $watch function.
// $rootScope = _$rootScope_;
$scope = _$rootScope_.$new();
// $http = _$http_;
// $routeParams = _$routeParams_;
controller = $controller('MainCtrl', {
$scope: $scope,
// $http: $http,
// $rootScope: $rootScope,
// $routeParams: $routeParams
});
}));
describe('$scope.sayHello', function() {
it('same tests', function() {
$scope.name = 'Girish';
$scope.sayHello();
expect($scope.greeting).toEqual('Hello Girish');
});
});
});
I new in AngularJS and try Unit Testing.I am using Karma and Jasmine. I created the first test for my controller but its not working and I don't know why karma throughs an error.
So please help me out this.
BasicTabCtrl.js
// Basic Tab Controller
myApp.controller('BasicTabCrtl', ['$scope', '$modal', 'BasicTabService', function ($scope, $modal, BasicTabService) {
console.log("BAsic tab crtl");
$scope.name = 'testing';
$scope.tab1 = "BASIC";
$scope.tab2 = "ADVANCE";
$scope.tab3 = "FORM";
$scope.user = {};
// get user from service
$scope.Tablelist = BasicTabService.getUser();
// delete user
$scope.deleteUser = function (obj) {
console.log("OBJ => " + JSON.stringify(obj));
if (obj != -1) {
$scope.Tablelist.splice(obj, 1);
}
}
}]);
Here is my test case
example.js
describe('myApp',function(){
var scope,controller;
beforeEach(function(){
module('myApp');
});
describe('BasicTabCrtl',function(){
beforeEach(inject(function($rootScope,$controller){
scope = $rootScope.$new();
controller=$controller('BasicTabCrtl',{
'$scope':scope
});
console.log("d");
}));
it('set the name',function(){
expect(scope.name).toBe('testing');
});
});
});
Error
26 05 2016 20:47:50.890:INFO [watcher]: Changed file "/home/rahul/Documents/django_project/myfirstsite/test/example.js".
Firefox 46.0.0 (Ubuntu 0.0.0) myApp BasicTabCrtl set the tab1 name FAILED
minErr/<#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:68:12
loadModules/<#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:4587:15
forEach#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:322:11
loadModules#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:4548:5
createInjector#/home/rahul/Documents/django_project/myfirstsite/static/js/angular.js:4470:19
workFn#/home/rahul/Documents/django_project/myfirstsite/static/js/angular-mocks.js:2954:44
TypeError: scope is undefined in /home/rahul/Documents/django_project/myfirstsite/test/example.js (line 19)
#/home/rahul/Documents/django_project/myfirstsite/test/example.js:19:3
Firefox 46.0.0 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.023 secs / 0.018 secs)
I believe the injection isn't working because of missing _ around angular methods
describe('myApp',function(){
var scope,controller;
beforeEach(function(){
module('myApp');
});
describe('BasicTabCrtl',function(){
beforeEach(inject(function(_$rootScope_, _$controller_){
scope = _$rootScope_.$new();
controller = $controller('BasicTabCrtl',{
'$scope':scope
});
console.log("d");
}));
it('set the name',function(){
expect(scope.name).toBe('testing');
});
});
});
Try this :
Create controller instance :
callController = function () {
return $controller('BasicTabCrtl', {
$scope: scope,
$routeParams: routeParams
});
};
Then test that it's defined or not . If this test pass then you can continue with unit test.
describe('null test', function () {
it('controller should be defined', function () {
ctrl = callController();
expect(ctrl).to.not.be.undefined;
});
});
The problem with your code is you are not injecting all of the dependencies when you instantiate your controller. Try this...
beforeEach(inject(['$scope', '$modal', 'BasicTabService', '$controller', '$rootScope', function ($scope, $modal, BasicTabService, $controller, $rootScope){
scope = $rootScope.$new();
controller=$controller('BasicTabCrtl',{
'$scope':$scope,
'$modal':$modal,
'BasicTabService': BasicTabService
});
console.log("d");
}));
Try my answer from Jasmine, Karma, Angular how to write test on my Angular app?. I describe how to test controllers and services and directives.
This is my factory / base.js:
angular.module("BaseApp", [])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}])
.config(['$locationProvider', function($locationProvider){
$locationProvider.html5Mode(true);
}])
.factory("BaseService", ["$http", "$window", function($http, $window) {
And this is my test_base.js:
describe('Factory: BaseService', function() {
var fctry, mockBackend;
beforeEach(function() {
module('BaseApp');
inject(function($factory, $httpBackend) {
mockBackend = $httpBackend;
fctry = $factory('BaseService', {});
});
});
it('logout() should POST to /logout', function() {
// I want to test if the logout(cb) function posts to /logout and, on success, redirect to '/'
// but on failure, calls accessErrors and the cb.
});
});
This is my karma config file:
files: [
'../angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'../base.js',
'tests/test_base.js',
],
When I do karma start and run the tests, I get this error / fail:
Chromium 48.0.2564 (Ubuntu 0.0.0) Factory: BaseService logout() should POST to /logout FAILED
Error: [$injector:unpr] Unknown provider: $factoryProvider <- $factory
http://errors.angularjs.org/1.3.15/$injector/unpr?p0=%24factoryProvider%20%3C-%20%24factory
...
Chromium 48.0.2564 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) (0 secs / 0.053 secChromium 48.0.2564 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.114 secs / 0.053 secs)
How come it is failing already and how come it is saying that $factoryProvider is an unknown provider?
It thinks you're trying inject factory, which is a function, not a provider, so that won't work.
You're also missing out on the underscore trick
Try changing this:
var fctry, mockBackend;
beforeEach(function() {
module('BaseApp');
inject(function($factory, $httpBackend) {
mockBackend = $httpBackend;
fctry = $factory('BaseService', {});
});
});
To this:
var BaseService, $httpBackend;
beforeEach(function() {
module('BaseApp');
inject(function(_BaseService_, _$httpBackend_) {
$httpBackend = _$httpBackend_;
BaseService = _BaseService_;
});
});
Trying to test a simple test in Jasmine & Karma and AngularJs frameWork,
controller:
(function() {
'use strict';
angular
.module('bsp.account')
.controller('Account', Account);
/* #ngInject */
function Account(userService, accountService) {
var vm = this;
vm.title = 'Accounts';
vm.username = userService.getUsername();
vm.showPasswordModal = accountService.showPasswordModal;
vm.showLogoutModal = accountService.showLogoutModal;
activate();
////////////////
function activate() {
}
}
})();
Can anyOne tell me how do i write a simple test case using Jasmin with this code ? and also maybe a possible methode and its test,
My test code below:
describe('Account', function() {
var scope,
controller;
beforeEach(module('bsp.account'));
//sample testCase--
it('testCheck', function() {
expect('helloWorld').toBe("helloWorld");
});
describe('Account', function() {
//injecting the scope&controller--
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('Account', {
$scope: scope
});
scope.vm = controller;
}));
});
it("checkTitle",function(){
var vm = controller("Account",{$scope:scope});
expect(vm.title).toEqual("Accounts");
});
});
karma ,response:
Running "karma:unit:run" (karma) task
[2015-10-23 15:11:03.542] [DEBUG] config - Loading config /vagrant/frontend/build/karma-unit.js
✗ checkTitle
TypeError: 'undefined' is not a function (evaluating 'controller("Account",{$scope:scope})')
at /vagrant/frontend/src/app/account/account.controller.spec.js:33
LOG LOG: undefined
PhantomJS 1.9.8 (Linux 0.0.0) LOG: undefined
LOG LOG: '** if *********'
PhantomJS 1.9.8 (Linux 0.0.0) LOG: '** if *********'
PhantomJS 1.9.8 (Linux 0.0.0): Executed 37 of 37 (1 FAILED) (0.134 secs / 0.128 secs)
Warning: Task "karma:unit:run" failed. Use --force to continue.
Aborted due to warnings.
Completed in 10.849s at Fri Oct 23 2015 15:11:04 GMT-0700 (PDT) - Waiting...
Any suggestions is appreciated,Am new to Jasmin testing.Thank You
You are actually instantiating a BoardPerformance controller in your beforeEach block but the code you are showing is for Account, so I understand that's a mistake.
So for your simple test case to run try this:
describe('Account', function() {
var scope, controller, userServiceMock;
beforeEach(module('bsp'));
beforeEach(function() {
userServiceMock = {
getUsername: function(){}
}
});
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('Account', {
'userService': userServiceMock
});
}));
it('checkTitle', function(){
expect(controller.title).toEqual('Accounts');
});
});
So this is the new test case in Jasmin,
describe('Account', function() {
var scope, controller, userServiceMock,accountServiceMock;
beforeEach(module('bsp'));
beforeEach(function() {
userServiceMock = {
getUsername: function(){} //this is a method inside userService
};
accountServiceMock = {
showPasswordModal :function(){}//this is a method inside accountService
};
});
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('Account', {
'userService': userServiceMock,
'accountService':accountServiceMock
});
}));
describe('testing Title',function(){
it('checkTitle', function(){
expect(controller.title).toEqual('Accounts');
});
});
});
It is very basic but has necessary information for controllers with dependency and also the vm..thank to Pablo