DieuNQ
DieuNQ

Reputation: 985

How can I write a test for $cookieStore like this?

I have 2 roles: one is admin, this another is normal user. Admin can navigate to item-detail page, and normal user can not. Hence, I store user's role in "globals" cookies when they are login. I get their role from cookieStore to check which one can navigate to item-detail page. This function works well. However, I have no idea how to write a test for $cookieStore in checkUserRole function:

angular.module('config', ['ui.router'])
.config(function($stateProvider, $urlRouterProvider) 
{
    $urlRouterProvider.otherwise('/login');
    $stateProvider
    .state('login', 
    {
        url: '/login',
        templateUrl: 'login-page.html',
        controller: 'LoginController'
    })
    .state('index',
    {
        url: '/index',
        templateUrl: 'bridge.html'
    })
    .state('item-detail',
    {
        url: '/index/item-detail/:Name',
        templateUrl: 'item-detail.html',
        controller: 'myCtrl',
        resolve:
        {
            checkUserRole: function($cookieStore)
            {
                if($cookieStore.get('globals').currentUser.userRole === 'user')
                {
                    return state.go('index');
                }
            }
        }
    });
});

And, here is my test case:

describe('config', function()
{
    var $scope, $state, $cookieStore, userRole;
    beforeEach(function()
    {
        module('config', function($provide)
        {
            $provide.value('$cookieStore', { get: 'globals' });
        });
        inject(function($injector, $templateCache)
        {
            $scope = $injector.get('$rootScope');
            $state = $injector.get('$state');
            $cookieStore = $injector.get('$cookieStore');
            $templateCache.put('login-page.html', '');
            $templateCache.put('bridge.html', '');
            $templateCache.put('item-detail.html', '');
        });
    });
    it('home page', function()
    {
        $scope.$apply();
        expect($state.current.name).toBe('login');
        expect($state.current.templateUrl).toBe('login-page.html');
        expect($state.current.controller).toBe('LoginController');
    });
    it('login page', function()
    {
        $scope.$apply(function()
        {
            $state.go('login');         
        });
        expect($state.current.name).toBe('login');
        expect($state.current.templateUrl).toBe('login-page.html');
        expect($state.current.controller).toBe('LoginController');
    });
    it('items page', function()
    {
        $scope.$apply(function()
        {
            $state.go('index');         
        });
        expect($state.current.name).toBe('index');
        expect($state.current.templateUrl).toBe('bridge.html');
    });
    it('item-detail page', function()
    {
        spyOn($cookieStore, 'get').and.callFake(function()
        {
            return 'user';
        });
        expect($cookieStore.get('globals')).toBe('user');
        $scope.$apply(function()
        {
            $state.go('item-detail');
        });
        expect($state.current.name).toBe('item-detail');
        expect($state.current.templateUrl).toBe('item-detail.html');
        expect($state.current.controller).toBe('myCtrl');
        expect($state.href('item-detail', { Name: 'lumia-950'})).toEqual('#/index/item-detail/lumia-950');
    });
});

My question is: How can I write a test for $cookieStore.get('globals').currentUser.userRole? or how can I mock it to test what if user's role is user?.

Upvotes: 0

Views: 840

Answers (1)

Freezystem
Freezystem

Reputation: 4884

I don't know what version of angular you're using but $cookieStore is now deprecated, prefer using $cookies instead (see doc).

There are at least 3 ways to proceed :

Using Jasmine with Angular $cookie (from v1.4.x) :

describe('config module', function(){
    var $cookies;

    beforeEach(function(){
        angular.mock.module('config');
        angular.mock.inject(function(_$cookies_){
            $cookies  = _$cookies_;
        });
    });

    it('should have a "globals" cookie with "user" value', function(){
        var globals = $cookies.getObject('globals');

        expect(globals.currentUser.userRole).toBe('user');
    });
});

Using Jasmine with pure JavaScript :

describe('config module', function(){
    it('should have a "globals" cookie with "user" value', function(){
        var globals = document.cookie.replace(/(?:(?:^|.*;\s*)globals\s*\=\s*([^;]*).*$)|^.*$/, "$1");
        globals = JSON.parse(globals);

        expect(globals.currentUser.userRole).toBe('user');
    });
});

Using Jasmine with Protractor (e2e test) :

describe('config module', function(){
    it('should have a "globals" cookie with "user" value', function(){
        var globals = JSON.parse(browser.manage().getCookie('globals'));
        expect(globals.currentUser.userRole).toBe('user');
    });
});

Here Protractor gives us browser global variable to handle browser related behavior.

Note that JSON.parse() is used to unserialized the cookie string value and parse it to an usable JavaScript object.

example :

var obj = JSON.parse('{ "foo" : "bar" }');
console.log(obj.foo);    //print 'bar' in the console

IMPORTANT:

In your application, use only 1.4.7 version of Angular libraries with the Angular 1.4.7 Core.

Let me know if it helps.

Upvotes: 1

Related Questions