Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS, Unit testing a directive that uses a service that depends on some resources

I am trying to unit test a directive that is using a service that uses some resources. The issue that I have is when I mock the get method of my resource it will be mocked but the callback function will not be called. Therefore, the result won't be what is expected.

I tried to mock the resources by using spyOn as suggested here, and also $httpBackend.when, but neither worked. When I debug the code it will get to the get method but the get callback function never gets called and therefore, the inner callback myCallback that sets my value never gets called. I am not sure if my approach is even correct, I appreciate your suggestions.

/ Resource

.factory ('AirportTimeZone', function($resource){
  return $resource('/api/airport/:airportId/timezone',{airportId: '@airportId'});
})

/ Service that is using my resources:

angular.module('localizationService', [])
.factory('LocalizationService', ['AirportTimeZone','CurrentLocalization',
     function (AirportTimeZone,CurrentLocalization) {

    function getAirportTimeZone(airport,myCallback){
      var options = {}
      var localOptions = AirportTimeZone.get({airportId:airport}, function(data){
          options.timeZone = data.timeZoneCode
          myCallback(options)
      });
    }
})

/ Directive

.directive('date',function (LocalizationService) {
    return function(scope, element, attrs) {
        var airTimeZone
         function updateAirportTimeZone(_airportTimeZone){
            airTimeZone = _airportTimeZone.timeZone
            // call other stuff to do here
        }
        ....
        LocalizationService.getAirportTimeZone(airport,updateAirportTimeZone)
        ....
        element.text("something");
    }
});

/ Test

describe('Testing date directive', function() {
    var $scope, $compile;
    var $httpBackend,airportTimeZone,currentLocalization

    beforeEach(function (){
        module('directives');
        module('localizationService');
        module('resourcesService');
    });

    beforeEach(inject(function (_$rootScope_, _$compile_,AirportTimeZone,CurrentLocalization) {
        $scope = _$rootScope_;
        $compile = _$compile_;
        airportTimeZone=AirportTimeZone;
        currentLocalization = CurrentLocalization;

 //        spyOn(airportTimeZone, 'get').andCallThrough();
 //        spyOn(currentLocalization, 'get').andCallThrough();

    }));

    beforeEach(inject(function($injector) {
        $httpBackend = $injector.get('$httpBackend');
//        $httpBackend.when('GET', '/api/timezone').respond({timeZone:'America/New_York',locale:'us-en'});
//        $httpBackend.when('GET', '/api/airport/CMH/timezone').respond({timeZone:'America/New_York'});
    }))

    describe('Date directive', function () {
        var compileButton = function (markup, scope) {
            var el = $compile(markup)(scope);
            scope.$digest();
            return el;
        };

        it('should',function() {
            var html = "<span date tz='airport' format='short' airport='CMH' >'2013-09-29T10:40Z'</span>"
            var element = compileButton(html,$scope)
            $scope.$digest();

            expected = "...."
            expect(element.html()).toBe(expected);


        });
    });
})
like image 302
Alidad Avatar asked Oct 02 '22 17:10

Alidad


1 Answers

As commented above:

After setting up responses with $httpBackend.when, you will still need to call $httpBackend.flush() to flush out the mocked response.

References: http://docs.angularjs.org/api/ngMock.$httpBackend - flushing http requests section

like image 167
Andyrooger Avatar answered Oct 20 '22 13:10

Andyrooger