1

I am trying to write a unit test for my ui-router with uses resolve.

Router.js

define(['module', 'require'], function(module, require) {
    'use strict';

    var Router = function ($stateProvider, $urlRouterProvider) {

        $urlRouterProvider.otherwise('/shopping');

        $stateProvider
            .state('shopping', {
                url: '/shopping',
                templateUrl: 'app/shopping.html',
                resolve:{
                    userFactory : 'UserFactory',
                    checkAccess:function(userFactory){
                        return userFactory.checkUser();
                    }
                }
            })
            .state('products', {
                url: '/products',
                templateUrl: 'app/products.html',
                resolve:{
                    userFactory : 'UserFactory',
                    checkAccess:function(userFactory){
                        return userFactory.checkUser();
                    }
                }
            })
            .state('notAuth', {
                url: '/notAuth',
                templateUrl: 'app/unauthorised.html'
            });
    };

    module.exports = ['$stateProvider', '$urlRouterProvider', Router];
});

Within userFactory.checkUser(); i essentially check the users' rights, and redirect either to the templateUrl, or perform a:

$state.go('notAuth');

My currect .spec.js:

define(['require', 'angular-mocks', 'angular-ui-router', 'app/router'], function (require) {
    'use strict';
    describe('myApp/myState', function() {

        var $rootScope, $state, $injector, myServiceMock, $httpBackend, state = 'shopping';

        var mockResponse = {
            "access": true
        }

        var angular = require('angular');
        var myRouter = require('app/router');

        beforeEach(module('ui.router'));

        beforeEach(function() {

            module(myRouter, function($provide) {
                $provide.value('userFactory', myServiceMock = {});
            });

            inject(function(_$rootScope_, _$state_, _$injector_, $templateCache, _$httpBackend_) {
                $rootScope = _$rootScope_.$new();
                $state = _$state_;
                $injector = _$injector_;
                $httpBackend = _$httpBackend_;
                $rootScope.$digest();
            })
        });

        it('should transition to shopping', inject(function($state,$rootScope){
            $state.transitionTo('shopping');
            $rootScope.$apply();
            expect($state.current.name).toBe('shopping');
        }));

        it('should resolve data', function() {
            myServiceMock.checkUser = jasmine.createSpy('checkUser').and.returnValue(mockResponse);
            // earlier than jasmine 2.0, replace "and.returnValue" with "andReturn"

            $state.go(state);
            $rootScope.$digest();
            expect($state.current.name).toBe(state);
        });
    });
});

With the above test, i get the following errors:

Information:  myApp/myState
Information:    should transition to shopping   Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Information:    Watchers fired in the last 5 iterations: []
Information:    http://errors.angularjs.org/1.4.0/$rootScope/infdig?p0=10&p1=%5B%5D

Information:    should resolve data Expected '' to be 'shopping'.
0

1 Answer 1

3

It looks like there are a few things happening here. First, you're digesting too many times. That's the "10 $digest() iterations reached" message. To fix that one, you should remove the $rootScope.$digest() from the end of your inject function.

I think the actual failing test part is because you're not resolving your checkAccess resolve that you've configured in your route. Try adding $provide.value('checkAccess', function() {return true;}); to your $provide.value setup. That should allow checkAccess to resolve in your route, which will then allow the route to complete the state transition.

I found my answer to a similar question here: Angular Jasmine UI router inject resolve value into test

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.