Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jasmine unit test case for $routeChangeStart in AngularJS

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?

like image 918
BKM Avatar asked Sep 30 '13 11:09

BKM


2 Answers

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.

like image 182
dnc253 Avatar answered Oct 14 '22 08:10

dnc253


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);
    });
  });
like image 22
unludo Avatar answered Oct 14 '22 08:10

unludo