In one of my controllers I have a location.reload()
(For those who wants to know why, My login page does not load the entire app before the user logs in to reduce threshold on the server)
When I test the controller (using jasmine html for the ui), it actually reloads the test in an infinite loop.
My questions is this:
How do I avoid the location.reload() from loading the test itself, and how do I even check whether it has been called? can I mock it somehow?
Here's the code for the controller:
(function() {
'use strict';
angular
.module('app.ctrls')
.controller('LoginController', LoginController);
LoginController.$inject = [ '$scope', 'AuthService' ];
function LoginController($scope, AuthService)
{
console.log('LoginController');
$scope.credantials = {
email: '',
password: '',
remember: false
}
$scope.login = function(credantials)
{
AuthService.login(credantials.email, credantials.password, credantials.remember || false).success(function(response) {
console.log(response);
if (response.email !== null)
{
$scope.logged = true;
console.log('login successful');
location.reload();
}
else
{
$scope.logged = false;
$scope.error = true;
}
}).error(function() {
console.log('failed to login');
});
};
}
})();
Here's the spec:
describe("successfully logged in", function() {
it("should reload the page", function() {
this.scope.credantials = { email: '[email protected]', password: '123', remember: false };
this.$httpBackend.expectPOST('/auth/login', this.scope.credantials).respond({first_name: "Bakayaru", email: "[email protected]"});
this.$httpBackend.whenGET('/tpls/home.html').respond(200);
this.scope.login(this.scope.credantials);
this.$httpBackend.flush();
expect(this.scope).toBeDefined();
expect(this.scope.logged).toBeTruthy();
/* -------> TEST that location.reload() has been called HERE <--------- */
});
});
I am not sure what you mean by "not loading itself" but anyways it is possible to mock the .reload() in tests. I did it in my App by first of all using Angular service $window.location instead of native javascript location in my App like this after injection $window as dependency to my controller:
$window.location.reload();
Then in the spec file I have the following (with one example test case using the mocked reload):
describe('Controller: MyCtrl', function () {
// load the controller's module
beforeEach(module('myApp'));
var MyCtrl,
scope,
mockBackend,
window;
beforeEach(function(){
inject(function(_$httpBackend_, $controller, $rootScope, $window) {
scope = $rootScope.$new();
mockBackend = _$httpBackend_;
window = $window;
spyOn(window.location, 'reload');
myCtrl = $controller('MyCtrl', {
$scope: scope,
$window: window
});
});
});
it('logout should fail if $window.reload() is called on unsuccessful logout call', function(){
scope.logout();
mockBackend.expectGET('/rest/session/logout').respond(404);
mockBackend.flush();
expect(window.location.reload.calls.count()).toEqual(0);
mockBackend.verifyNoOutstandingExpectation();
mockBackend.verifyNoOutstandingRequest();
});
});
This is a bit differently structured to your spec file, but I hope this example clarifies how to mock $window object and use spies on it.
You can mock $window in your test like this:
describe('service', function () {
var $window;
beforeEach(module('core', function ($provide) {
$window = {
location:{
reload: jasmine.createSpy()
}
};
$provide.value('$window', $window);
}));
});
This way it will "override" the default behaviour of $window.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With