Angular 1.5 test component with jasmine - javascript

I try test my component with Jasmine and Angular-mock, but I don't know how this do.
This is my component
var angular = require('angular');
'use strict';
module.exports = angular
.module('app.login.component.login', [])
.component('login', {
templateUrl: '/app/js/login/components/login.template.html',
controller: LoginController
});
LoginController.$inject = ['$state', 'Auth', 'messages'];
function LoginController($state, Auth, messages) {
var ctrl = this;
ctrl.failMessage = messages.NO_AUTH;
ctrl.failResponse = false;
ctrl.login = login;
function login(user){
ctrl.errors = {};
Auth.login(user)
.success(function(result){
$state.go('profile');
})
.error(function(response) {
ctrl.failResponse = true;
})
};
}
I write this test but his dosen't work.
Please explain me what I do wrong and show some pattern how test component
describe('Component: login', function() {
beforeEach(angular.mock.module(require('angular-ui-router')));
beforeEach(angular.mock.module(loginComponent.name));
var scope;
beforeEach(inject(function($rootScope, $compile){
scope = $rootScope.$new();
}));
var controller;
beforeEach(inject(function($componentController, Auth) {
ctrl = $componentController('login', {
$scope:scope});
}));
it('df', function() {
expect(ctrl.login).toBeDefined();
});
});

You use $componentController.
beforeEach(inject(function($rootScope, $componentController){
scope = $rootScope.$new();
controller = $componentController('myComponent', {$scope: scope});
}));

Related

karma test controller using toBeDefined failed

My test failed because it says my controller is not defined. So strange I think I did everything right.
describe('homeCtrl', function() {
var httpBackend, controller, scope;
beforeEach(module('App'));
beforeEach(inject(function($httpBackend, $controller) {
scope = {};
httpBackend = $httpBackend;
controller = $controller('homeCtrl', { $scope: scope });
}));
it('should exist', function() {
expect(controller).toBeDefined();
});
});
and I have my home.js which is the controller like this
var App = angular.module('App')
App.controller('homeCtrl', function($scope) {
})
The error is Expected undefined to be defined.
Your home.js should have dependencies injected in module, change it as,
var App = angular.module('App',[])
App.controller('homeCtrl', function($scope) {
})

Not a function (mocking error?)

I'm trying to do some unit testing on my Ionic app, using the Karma-jasmine framework, and it's giving me quite the headache. I have a function in my controller I want to test by giving it some dummy input (the credentials), but I keep getting the errors
TypeError: 'undefined' is not a function (evaluating '$controller')
TypeError: 'undefined' is not an object (evaluating '$scope.credentials.username = "uname"')
I've tried some alternate ways to do this, but one of them kept giving me some bogus that I needed to add dependencies from my services.js as well (i.e. $ionicPopup), which might have some truth to it, but I'm super new to all of this. Any help would be greatly appreciated.
I've made a lot of progress by mostly rewriting this, but I'm now getting the error
TypeError: 'undefined' is not a function (evaluating 'LoginService.initiateRequest(
$scope.credentials.username,
$scope.credentials.password)')
at c:/Users/name/git/mobile/www/js/controllers.js:18
It's saying that it's not a function in my controllers.js file...which it DEFINITELY is. Really not understanding this one. Is it something to do with services?
I have here my controllers.tests.js file...
describe('Controllers', function() {
beforeEach(module('myApp.services', 'myApp.controllers'));
var mockRequest = {
}
beforeEach(function() {
module(function($provide) {
$provide.value('initiateRequest', mockRequest);
});
});
var $rootScope, $controller, $sharedProperties, $resource;
beforeEach(inject(function(_$controller_, $rootScope) {
myScope = $rootScope.$new();
$scope = {};
$state = {};
LoginService = {};
localStorageService = {};
sharedProperties = {};
$ionicLoading = myScope;
initiateRequest = mockRequest;
$controller = _$controller_;
}));
describe('$scope.login()', function() {
it('does something', function() {
var $scope = {};
var controller = $controller('LoginController', {
$scope: $scope,
$state: $state,
LoginService: LoginService,
localStorageService: localStorageService,
sharedProperties: sharedProperties,
$ionicLoading: $ionicLoading
});
expect($scope.login).toBeDefined(true);
expect($scope.show).toBeDefined(true);
$scope.login();
});
});
});
describe('Controllers', function () {
beforeEach(module('myApp.services', 'myApp.controllers'));
var mockRequest = {};
beforeEach(function () {
module(function ($provide) {
$provide.value('initiateRequest', mockRequest);
});
});
var $controller, sharedProperties, state, scope, ionicLoading, LoginService, localStorageService, initiateRequest;
beforeEach(function () {
inject(function ($rootScope, _$controller_) {
scope = $rootScope.$new();
$controller = _$controller_;
ionicLoading = {};
sharedProperties = {};
LoginService = {};
localStorageService = {};
initiateRequest = mockRequest;
});
});
describe('$scope.login()', function () {
beforeEach(function () {
$controller('LoginController', {
$scope: scope,
$state: state,
LoginService: LoginService,
localStorageService: localStorageService,
sharedProperties: sharedProperties,
$ionicLoading: ionicLoading
});
scope.$apply();
});
it('does something', function () {
expect(scope.login).toBeDefined();
expect(scope.show).toBeDefined();
});
});
});

expected scope variable undefined in karma test

I'm having trouble understanding how the scope gets initialized in karma tests. i'm expecting a scope variable to be preset when the test runs, but it keeps coming back as undefined.
What am I missing?
Test Case
describe('loginController', function() {
beforeEach(module('app'));
var $controller, $scope;
beforeEach(inject(function(_$controller_, $rootScope){
$controller = _$controller_;
$scope = $rootScope.$new();
}));
describe('$scope.login', function() {
beforeEach(function() {
controller = $controller('loginController', { $scope: $scope });
});
it('checks it initialized', function() {
expect($scope.foo).toEqual('foo');
expect($scope.bar).toEqual('bar');
//expect($scope).toBeDefined();
//expect($scope.loginData.userName).toEqual('');
//expect($scope.loginData.password).toEqual('');
});
The controller:
angular.module('app').controller('loginController', ['$location',
'authService', function($scope, $location, authService) {
$scope.foo = 'foo';
$scope.bar = 'bar';
$scope.loginData = {
userName: '',
password: ''
};
}]);
I refactored the test code and now it works:
describe('loginController', function() {
beforeEach(module('app'));
var controller, scope;
beforeEach(inject(function($controller, $rootScope){
scope = $rootScope.$new();
console.log('scope1', scope);
controller = $controller('loginController', {
$scope: scope
});
}));
describe('login', function() {
it('sets variables ', function() {
expect(scope).toBeDefined();
expect(scope.loginData).toBeDefined();
expect(scope.loginData.userName).toEqual('');
expect(scope.loginData.password).toEqual('');
});
});
});
try injecting $controller to the function where you instantiate the controller:
beforeEach(inject(function($controller) {
controller = $controller('loginController', { $scope: $scope });
}));

Call a controller function from Karma and Jasmine testing

This is my angular controller :-
angular.module('authoring-controllers', []).
controller('NavCtrl', function($scope, $location, BasketNavigationService) {
$scope.test= function() {
$scope.testVar = BasketNavigationService.showBasketList();
};
});
TEST class
describe('NavCtrl', function() {
var scope, $location, createController;
beforeEach(inject(function ($rootScope, $controller, _$location_) {
$location = _$location_;
scope = $rootScope.$new();
createController = function() {
return $controller('NavCtrl', {
'$scope': scope
});
};
}));
it('should create $scope.testVar when calling test',
function() {
expect(scope.testVar).toBeUndefined();
scope.test();
expect(scope.testVar).toBeDefined();
});
});
Getting an error when i run that test case :- scope.test() is undefined..
If i removed BasketNavigationService functionality from controller then it is working..
Please help me to solve that karma test case.
here is the working demo , hope it helps.
problem was with injecting the dependencies.
//--- CODE --------------------------
(function(angular) {
// Create module
var myApp = angular.module('myApp', []);
// Controller which counts changes to its "name" member
myApp.controller('MyCtrl', ['$scope', 'BasketNavigationService',
function($scope, BasketNavigationService) {
$scope.test = function() {
$scope.testVar = BasketNavigationService.showBasketList();;
};
}
]);
})(angular);
// ---SPECS-------------------------
describe('myApp', function() {
var scope,
controller;
beforeEach(function() {
module('myApp');
});
describe('MyCtrl', function() {
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('MyCtrl', {
'$scope': scope,
'BasketNavigationService': {
showBasketList: function() {
return null;
}
}
});
}));
it('should create $scope.testVar when calling test',
function() {
expect(scope.testVar).toBeUndefined();
scope.test();
// scope.$digest();
expect(scope.testVar).toBeDefined();
});
});
});
// --- Runner -------------------------
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function(spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
<script src="http://jasmine.github.io/1.3/lib/jasmine.js"></script>
<script src="http://jasmine.github.io/1.3/lib/jasmine-html.js"></script>
<script src="https://code.angularjs.org/1.2.9/angular.js"></script>
<script src="https://code.angularjs.org/1.2.9/angular-mocks.js"></script>
<link href="http://jasmine.github.io/1.3/lib/jasmine.css" rel="stylesheet" />
fiddle : http://jsfiddle.net/invincibleJai/pf1deoom/1/
Please change your createController setup to:
createController = function() {
return $controller('NavCtrl', {
'$scope': scope,
'$location':$location,
'BasketNavigationService':{showBasketList: function(){return 'test'} }
});
};
You are not injecting all the dependencies.
I have injected dummy BasketNavigationService, you can inject the real one.
Have you tried running createController();? I don't think your NavCtrl controller gets mocked.

$scopeProvider <- $scope/ Unknown provider

I testing my angular-application with jasmine(http://jasmine.github.io/2.0/) and getting next error:
Unknown provider: $scopeProvider <- $scope
I know, that it's incorrect to build dependency with scope in filters, services, factories, etc., but I use $scope in controller!
Why am i getting this error? controller looks like
testModule.controller('TestCont', ['$filter', '$scope', function($filter, $scope){
var doPrivateShit = function(){
console.log(10);
};
this.lol = function(){
doPrivateShit();
};
this.add = function(a, b){
return a+b;
};
this.upper = function(a){
return $filter('uppercase')(a);
}
$scope.a = this.add(1,2);
$scope.test = 10;
$scope.search = {
};
}]);
and my test's code:
'use strict';
describe('testModule module', function(){
beforeEach(function(){
module('testModule');
});
it('should uppercase correctly', inject(function($controller){
var testCont = $controller('TestCont');
expect(testCont.upper('lol')).toEqual('LOL');
expect(testCont.upper('jumpEr')).toEqual('JUMPER');
expect(testCont.upper('123azaza')).toEqual('123AZAZA');
expect(testCont.upper('111')).toEqual('111');
}));
});
You need to manually pass in a $scope to your controller:
describe('testModule module', function() {
beforeEach(module('testModule'));
describe('test controller', function() {
var scope, testCont;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
testCont = $controller('TestCont', {$scope: scope});
}));
it('should uppercase correctly', function() {
expect(testCont.upper('lol')).toEqual('LOL');
expect(testCont.upper('jumpEr')).toEqual('JUMPER');
...
});
});
});
Normally, a $scope will be available as an injectable param only when the controller is attached to the DOM.
You need to associate somehow the controller to the DOM (I'm mot familiar with jasmine at all).
I am following a video tutorial from egghead (link bellow) which suggest this approach:
describe("hello world", function () {
var appCtrl;
beforeEach(module("app"))
beforeEach(inject(function ($controller) {
appCtrl = $controller("AppCtrl");
}))
describe("AppCtrl", function () {
it("should have a message of hello", function () {
expect(appCtrl.message).toBe("Hello")
})
})
})
Controller:
var app = angular.module("app", []);
app.controller("AppCtrl", function () {
this.message = "Hello";
});
I am posting it because in the answer selected we are creating a new scope. This means we cannot test the controller's scope vars, no?
link to video tutorial (1min) :
https://egghead.io/lessons/angularjs-testing-a-controller

Categories