Search code examples
javascriptangularjsjasmineonblur

how do i test javascript function with nested timeouts using jasmine


I have the following function that will simply clear an input on blur. I'm using angular materials, and I'm creating a directive to be added when I want that to happen.

   function clearTextOnBlurLink(scope, element, attrs, controller) {   
            $timeout(function() {
                var input = element.find('input'); 
                input.on('blur', function(e){
                    setTimeout(function(){
                        input.val('');              
                        input.triggerHandler('input'); 
                    }, 100);                
                });
            },0);
        }

I want to test it, but I can't get it to work.

Here's my test:

    beforeEach(inject(function(_$rootScope_, _$compile_, _$timeout_) {

                $scope = _$rootScope_.$new();
                $compile = _$compile_;
                $timeout = _$timeout_;        
                $scope.searchText = 'blah';

                element = angular.element('\
                    <div mx-clear-on-blur> <input ng-model="searchText1"> </div>\
                ');

               element = $compile(element)($scope);
               $scope.$apply();
               $timeout.flush();       
      }));
 it('clears text on blur', function() {
        var input = element.find('input').eq(0);

        expect(input.val()).toBe('blah');
        expect($scope.searchText).toBe('blah');

        input1.triggerHandler('blur');

        expect(input.val()).toBe('');
        expect($scope.searchText).toBe('');


    });

Ok, So I got it to work changing the setTimeout to $timeout. Is there a less clunky way of doing that without the 2 timeouts?


Solution

  • Is there any reason why you're using setTimeout the second time around? Why not just use $timeout again...? Also $timeout is usually a bit of a code smell, so nested $timeouts feel a bit wrong tbh. :p

    Anyway, I think for your test to pass you'd need a $timeout.flush() in your test after the blur.