Markus Pint
Markus Pint

Reputation: 348

Jasmine, AngularJS change injected mock object after injection

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

Answers (1)

meilke
meilke

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

Related Questions