Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing the AngularJS $window service

Tags:

angularjs

I would like to unit test the following AngularJs service:

.factory('httpResponseInterceptor', ['$q', '$location', '$window', 'CONTEXT_PATH', function($q, $location, $window, contextPath){
     return {
         response : function (response) {
             //Will only be called for HTTP up to 300
             return response;
         },
         responseError: function (rejection) {
             if(rejection.status === 405 || rejection.status === 401) {
                 $window.location.href = contextPath + '/signin';
             }
             return $q.reject(rejection);
         }
     };
}]);

I have tried with the following suite:

describe('Controllers', function () {
    var $scope, ctrl;
    beforeEach(module('curriculumModule'));
    beforeEach(module('curriculumControllerModule'));
    beforeEach(module('curriculumServiceModule'));
    beforeEach(module(function($provide) {
       $provide.constant('CONTEXT_PATH', 'bignibou'); // override contextPath here
    }));
    describe('CreateCurriculumCtrl', function () {
        var mockBackend, location, _window;
        beforeEach(inject(function ($rootScope, $controller, $httpBackend, $location, $window) {
            mockBackend = $httpBackend;
            location = $location;
            _window = $window;
            $scope = $rootScope.$new();
            ctrl = $controller('CreateCurriculumCtrl', {
                $scope: $scope
            });
        }));

        it('should redirect to /signin if 401 or 405', function () {
            mockBackend.whenGET('bignibou/utils/findLanguagesByLanguageStartingWith.json?language=fran').respond([{"description":"Français","id":46,"version":0}]);
            mockBackend.whenPOST('bignibou/curriculum/new').respond(function(method, url, data, headers){
                return [401];
            });
            $scope.saveCurriculum();
            mockBackend.flush();
            expect(_window.location.href).toEqual("/bignibou/signin");
        });


    });
});

However, it fails with the following error message:

PhantomJS 1.9.2 (Linux) Controllers CreateCurriculumCtrl should redirect to /signin if 401 or 405 FAILED
    Expected 'http://localhost:9876/context.html' to equal '/bignibou/signin'.
PhantomJS 1.9.2 (Linux) ERROR
    Some of your tests did a full page reload!

I am not sure what is going wrong and why. Can anyone please help?

I just want to ensure the $window.location.href is equal to '/bignibou/signin'.

edit 1:

I managed to get it to work as follows (thanks to "dskh"):

 beforeEach(module('config', function($provide){
      $provide.value('$window', {location:{href:'dummy'}});
 }));
like image 428
balteo Avatar asked Feb 08 '14 11:02

balteo


People also ask

Is AngularJS code unit testable?

AngularJS is written with testability in mind, but it still requires that you do the right thing. We tried to make the right thing easy, but if you ignore these guidelines you may end up with an untestable application.

What is testing in AngularJS?

Testing in AngularJS is achieved by using the karma framework, a framework which has been developed by Google itself. The karma framework is installed using the node package manager. The key modules which are required to be installed for basic testing are karma, karma-chrome-launcher ,karma-jasmine, and karma-cli.

How is unit testing done in Angular?

Unit tests are written using Jasmine and are run to see if individual parts of an application are working correctly. As a result, unit tests will either pass or fail depending on if the code is working correctly or has a bug. Angular uses Karma as the test runner for the project's unit tests.


2 Answers

You can inject stub dependencies when you load in your module:

angular.mock.module('curriculumModule', function($provide){
            $provide.value('$window', {location:{href:'dummy'}});
        });
like image 103
Dan Avatar answered Oct 27 '22 15:10

Dan


To get this to work for me I had to make a minor adjustment. It would error out and say:

TypeError: 'undefined' is not an object (evaluating '$window.navigator.userAgent')

So I added the navigator.userAgent object to get it to work for me.

$provide.value('$window', {
  location:{
    href:'dummy'
  },
  navigator:{
    userAgent:{}
  }
});
like image 42
bcbrian Avatar answered Oct 27 '22 16:10

bcbrian