Question

Hi I am building an app using AngularJS and now I am on to the unit testing my application. I know how to write unit test cases for services, controllers etc. But I don't know to write it for $routeChangeStart.

I have following code in my app.js

app.run(function ($rootScope, $location, AuthenticationService) {
    $rootScope.$on('$routeChangeStart', function () {
        if (AuthenticationService.isLoggedIn()) {
            $rootScope.Authenticated = 'true';
            $rootScope.Identity = localStorage.getItem('identification_id');
        } else {
            $rootScope.Authenticated = 'false';
            $rootScope.Identity = localStorage.removeItem('identification_id');
        }
    });
});

I have written this code to find out whether the user is logged in or not for each routing in my app. I have written a service AuthenticationService for this purpose like;

app.factory('AuthenticationService', function (SessionService) {
    return {
        isLoggedIn: function () {
            return SessionService.get('session_id');
        }
    };
});

And my session service like;

app.factory('SessionService', function () {
    return {
        get: function (key) {
            return localStorage.getItem(key);
        }
    };
});

I am using Jasmine to write test cases and using Istanbul for code coverage. When I run my test using Grunt I am getting something like this in my app.js;

enter image description here

It's because I am not covering these statements in my test cases as I don't know how to write test case for this particular piece of code. Any suggestions?

Was it helpful?

Solution

That run block runs every time the module is loaded, so that listener is being registered during the tests. You just need that event to actually be sent so that you can test the code within it. Something like this should do the trick:

it("should test the $routeChangeStart listener", inject(function($rootScope) {
   $rootScope.$broadcast("$routeChangeStart");
   //expects for the listener
}));

See How can I test events in angular? for how to test events in general.

OTHER TIPS

A good way to test $rootScope.$on('$routeChangeStart',... may be found in the unit tests of angularjs itself. It is an excellent source of knowledge as every feature is tested, so it's possible to find good solutions. That's why unit test is so great, isn't it ?

https://github.com/angular/angular.js/blob/master/test/ngRoute/routeSpec.js

The following test (taken from angular head 1.2.x - follow the link for latest) works great, you just have to adapt to your test (as the event handler is already in your code):

'use strict';

describe('$route', function() {
  var $httpBackend;

  beforeEach(module('ngRoute'));

  beforeEach(module(function() {
    return function(_$httpBackend_) {
      $httpBackend = _$httpBackend_;
      $httpBackend.when('GET', 'Chapter.html').respond('chapter');
      $httpBackend.when('GET', 'test.html').respond('test');
      $httpBackend.when('GET', 'foo.html').respond('foo');
      $httpBackend.when('GET', 'baz.html').respond('baz');
      $httpBackend.when('GET', 'bar.html').respond('bar');
      $httpBackend.when('GET', 'http://example.com/trusted-template.html').respond('cross domain trusted template');
      $httpBackend.when('GET', '404.html').respond('not found');
    };
  }));

  it('should route and fire change event', function() {
    var log = '',
        lastRoute,
        nextRoute;

    module(function($routeProvider) {
      $routeProvider.when('/Book/:book/Chapter/:chapter',
          {controller: angular.noop, templateUrl: 'Chapter.html'});
      $routeProvider.when('/Blank', {});
    });
    inject(function($route, $location, $rootScope) {
      $rootScope.$on('$routeChangeStart', function(event, next, current) {
        log += 'before();';
        expect(current).toBe($route.current);
        lastRoute = current;
        nextRoute = next;
      });
      $rootScope.$on('$routeChangeSuccess', function(event, current, last) {
        log += 'after();';
        expect(current).toBe($route.current);
        expect(lastRoute).toBe(last);
        expect(nextRoute).toBe(current);
      });

      $location.path('/Book/Moby/Chapter/Intro').search('p=123');
      $rootScope.$digest();
      $httpBackend.flush();
      expect(log).toEqual('before();after();');
      expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', p:'123'});

      log = '';
      $location.path('/Blank').search('ignore');
      $rootScope.$digest();
      expect(log).toEqual('before();after();');
      expect($route.current.params).toEqual({ignore:true});

      log = '';
      $location.path('/NONE');
      $rootScope.$digest();
      expect(log).toEqual('before();after();');
      expect($route.current).toEqual(null);
    });
  });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top