I am trying to figure out how to properly inject the $window service into my angular controller, and then test to make sure it redirects appropriately. Currently, I am getting an error stating undefined is not a constructor (evaluating 'expect(window.location.href).toEqual('/profile')')
. A snippet of my angular controller is as follows:
login.submitLogin = function(){
LoginFactory.loginUser(login.dataset)
.then(function(response){
$window.location.href = '/profile'
},function(response) {
login.errorMessage = response.data.message;
});
};
My unit test in Karma is as follows:
describe('Login Controller', function() {
var controller, window;
beforeEach(angular.mock.module('app'));
beforeEach(inject(function(_$controller_, _$window_){
window = _$window_;
controller = _$controller_('LoginCtrl',window);
}));
describe('Login', function() {
it('expects controller to be defined', function(){
expect(controller).to.be.defined;
});
it('expects to be redirected after login', function() {
controller.dataset.username = 'username';
controller.dataset.password = 'password';
controller.submitLogin();
expect(window.location.href).toEqual('/profile');
});
});
});
I am trying to figure out how to properly inject the $window service into my angular controller, and then test to make sure it redirects appropriately. Currently, I am getting an error stating undefined is not a constructor (evaluating 'expect(window.location.href).toEqual('/profile')')
. A snippet of my angular controller is as follows:
login.submitLogin = function(){
LoginFactory.loginUser(login.dataset)
.then(function(response){
$window.location.href = '/profile'
},function(response) {
login.errorMessage = response.data.message;
});
};
My unit test in Karma is as follows:
describe('Login Controller', function() {
var controller, window;
beforeEach(angular.mock.module('app'));
beforeEach(inject(function(_$controller_, _$window_){
window = _$window_;
controller = _$controller_('LoginCtrl',window);
}));
describe('Login', function() {
it('expects controller to be defined', function(){
expect(controller).to.be.defined;
});
it('expects to be redirected after login', function() {
controller.dataset.username = 'username';
controller.dataset.password = 'password';
controller.submitLogin();
expect(window.location.href).toEqual('/profile');
});
});
});
Share
Improve this question
asked Aug 11, 2016 at 14:07
unseen_damageunseen_damage
1,3762 gold badges15 silver badges32 bronze badges
5
-
The correct syntax is
_$controller_('LoginCtrl', { $window: window })
. And mocked$window
service can be supplied to controller instead ofwindow
this way. – Estus Flask Commented Aug 11, 2016 at 15:05 -
I changed my code to the following :
$window = _$window_; controller = _$controller_('LoginCtrl', { $window: window });
in the beforeEach. I injectedexpect($window.location.href).toEqual('/profile')
and still get the exception. Do I need to mock the backend as Andrzej suggested? – unseen_damage Commented Aug 11, 2016 at 15:14 -
{ $window: window }
doesn't make sense because it is already equal towindow
. You need to stub$window
with{ location: {} }
object to not let the controller screw upwindow
global, this is what it is about. IfLoginFactory
does http request then sure, you need to mock it, too. The preferable way to do unit tests to mock everything but tested unit (includingLoginFactory
). – Estus Flask Commented Aug 11, 2016 at 15:20 -
So do you mean to say it should look like this?:
controller = _$controller_('LoginCtrl', {location: {} });
and then in the expect:expect(window.location.href).toEqual('/profile');
– unseen_damage Commented Aug 11, 2016 at 15:37 -
Real
$window
shouldn't be injected at all in this case, it is just not needed. You mock it with$windowMock = ...; _$controller_('LoginCtrl', { $window: $windowMock })
and then expect on$windowMock.location.href
. – Estus Flask Commented Aug 11, 2016 at 15:42
1 Answer
Reset to default 5One solution is just mock (overwrite) $window service in your tests:
beforeEach(function () {
module(function($provide) {
$provide.value('$window', {
location: {href: ''}
});
});
});
beforeEach(inject(function(_$controller_, _$window_){
window = _$window_;
controller = _$controller_('LoginCtrl',window);
}));
and then just check what has been assigned to $window.location.href by:
expect(window.location.href).toEqual('/profile');
also you need to use $httpBackend if LoginFactory.loginUser makes request to server:
it('expects to be redirected after login', function() {
var mockedResponse = {};
controller.dataset.username = 'username';
controller.dataset.password = 'password';
$httpBackend.whenPOST('/api/login/').respond(mockedResponse);
controller.submitLogin();
$httpBackend.flush();
expect(window.location.href).toEqual('/profile');
});