Reputation: 348
I want to test my factory in different situations such as the absence of a token, an expired token and a good token. I am having trouble with mocking the $window.localStorage. Here is my test code:
describe('Unit: Security Module', function () {
describe('Security factory', function() {
var windowMock, locationMock, security, $httpBackend, $http, $window, $location;
beforeEach(module('app.common.security', function($provide) {
locationMock = {
url: jasmine.createSpy().and.returnValue(true)
};
windowMock = {
localStorage: { token: false }
};
$provide.value('$location', locationMock);
$provide.value('$window', windowMock);
}));
beforeEach(inject(function(_$httpBackend_, _$window_, _$location_, _security_) {
$httpBackend = _$httpBackend_;
$window = _$window_;
$location = _$location_;
security = _security_;
}));
it("Should call location.url with '/login' if no token in localStorage", function() {
security.tokenCheck();
expect($location.url).toHaveBeenCalledWith('/login');
});
it("Should call location.url with '/login' and delete token if bad token", function() {
// Need to modify the windowMock.localStorage.token value here somehow
$httpBackend
.whenPOST('/api/tokenCheck', {token:"mockBadToken123"})
.respond (400, "Token invalid or undefined");
security.tokenCheck();
expect($location.url).toHaveBeenCalledWith('/login');
expect($window.localStorage.token).toBeUndefined();
});
});
});
My question is: if I want to modify the windowMock values, do I have to write all my tests like this?
it("good token", function () {
module('app.common.security', function ($provide) {
locationMock = {
url: jasmine.createSpy().and.returnValue(true)
};
windowMock = {
localStorage: { token: "mockBadToken123" }
};
$provide.value('$location', locationMock);
$provide.value('$window', windowMock);
});
inject(function (_$httpBackend_, _$window_, _$location_, _security_) {
$httpBackend = _$httpBackend_;
$window = _$window_;
$location = _$location_;
security = _security_;
})
$httpBackend
.whenPOST('/api/tokenCheck', {token: "mockBadToken123"})
.respond(400, "Token invalid or undefined");
security.tokenCheck();
expect($location.url).toHaveBeenCalledWith('/login');
expect($window.localStorage.token).toBeUndefined();
});
Or is there a more efficient way?
EDIT: The factory itself looks like this:
angular.module('app.common.security').factory('security', ['$http', '$window', '$location', function ($http, $window, $location) {
var Security = {};
Security.tokenCheck = function () {
if (!$window.localStorage.token) {
$location.url('/login');
return;
}
$http.post('/api/tokenCheck', {token: $window.localStorage.token})
.success(function (data) {
console.log("STUBB: set user data, login status and redirect to panel");
}).error(function (err) {
delete $window.localStorage.token;
$location.url('/login');
});
};
return Security;
}]);
Upvotes: 2
Views: 1642
Reputation: 3280
Why are you not doing just what you are saying you want to do in the test?
it("Should call location.url with '/login' and delete token if bad token", function() {
// Need to modify the windowMock.localStorage.token value here somehow
$window.localStorage = { token: "mockBadToken123" };
$location.url = jasmine.createSpy().and.returnValue(true);
$httpBackend
.whenPOST('/api/tokenCheck', {token:"mockBadToken123"})
.respond (400, "Token invalid or undefined");
security.tokenCheck();
$httpBackend.flush();
expect($location.url).toHaveBeenCalledWith('/login');
expect($window.localStorage.token).toBeUndefined();
});
Upvotes: 2