mercredi 22 juin 2016

Unit testing child state dependant on parent resolve to be completed first

I am trying to unit test a resolve function of a state that is the child of an abstract state.

The abstract state also has a resolve on and I require the abstract state resolve to be completed before the child state resolves. I have this working using the following configuration.

$stateProvider.state('common', {
    templateUrl: 'common.html',
    abstract: true,
    resolve: {
        checkUserAccess: checkUserAccess
    }
}).state('my-state', {
    parent: 'common',
    templateUrl: 'app/my-template.html',
    controller: 'MyController',
    controllerAs: 'vm',
    resolve: {
        something: getSomething,
    }
});


checkUserAccess.$inject = ['authService', 'userService'];
function checkUserAccess(authService, userService) {
    return authService.hasAccessToken().then(function(){
        return userService.getProfile();
    });
}

//Note that the checkUserAccess parent resolve key is injected here to tell this resolve to wait for checkUserAccess to resolve first
getSomething.$inject = ['checkUserAccess', 'someService'];
function getSomething(checkUserAccess, someService) {
    return someService.get();
}

The checkUserAccess resolve function first checks the user has a valid access token, and then grabs some user profile information.

The functions in the services that deal with these just return the promise of the underlying $http call:

//authService
function hasAccessToken(){
    return $http.get('/auth/checktoken');
}

//userService
function getProfile(){
    return $http.get('/users/profile');
}

So I am now trying to put together a unit test to check that when calling my-state, a call is made to someService.get() in the getSomething resolve function.

I have attempted the following test

describe('State Change: my-state', function(){
    var authService,
        userService,
        someService,
        $q;

    beforeEach(inject(function(_authService_, _userService_, _someService_, _$q_) {
        authService = _authService_;
        userService = _userService_;
        someService = _someService_;
        $q = _$q_;
        var deferredHasAccessToken = $q.defer(),
            deferredGetProfile = $q.defer();
        spyOn(authService, 'hasAccessToken').and.returnValue(deferredHasAccessToken.promise);
        spyOn(userService, 'getProfile').and.returnValue(deferredGetProfile.promise);
        spyOn(someService, 'get');
        $state.go('my-state');
        deferredHasAccessToken.resolve();
        deferredGetProfile.resolve()
    }));
    it('should make a call to someService.get', function() {
        expect(someService.get).toHaveBeenCalled();
    });
});

So I'm trying to resolve the chain of promises in the checkUserAccess for checking the users token and getting their profile details. My thinking is that once these are both resolved then this will resolve checkUserAccess fully in order for the child state's getSomething resolve to kick in.

I end up with the test failing as it expects someService.get() to have been called but it never is.

So I'm clearly missing something here, but I am struggling to figure out what I need.

Can anyone help?

Thanks

Aucun commentaire:

Enregistrer un commentaire