Pianoc
Pianoc

Reputation: 797

AngularJs unit-test for timeout

I have a angular directive with the following snippet of code, how would I unit test this?

 link: function($scope, iElm) {

            $(iElm).on('paste', function(){
                $timeout(function(){
                        $scope.lastScan = Date.now();
                    });
                }); 
            }

Upvotes: 0

Views: 570

Answers (1)

Matt Herbstritt
Matt Herbstritt

Reputation: 4862

You need to use $timeout.flush() which will instantly call any $timeout callbacks you have defined, so it essentially makes it into synchronous code for testing purposes.

Try this:

DEMO

app.js

app.directive('myDirective', function($timeout){

  return function($scope, iElm) {

    // no need to use jQuery
    iElm.bind('paste', function(){
      console.log('**paste**')
      $timeout(function(){
        console.log('timeout')
        $scope.lastScan = Date.now();
      });
    }); 

    // $(iElm).on('paste', function(){
    //   $timeout(function(){
    //           $scope.lastScan = Date.now();
    //       });
    //   }); 

  }

});

appSpec.js

describe("My directive", function() {

    var element,
        $timeout, $compile, $scope;


    // load the module that has your directive
    beforeEach(module('plunker'));

    beforeEach(inject(function(_$timeout_, _$compile_, _$rootScope_) {
        $timeout = _$timeout_;
        $compile = _$compile_;
        $scope   = _$rootScope_.$new();
    }));

    function compileElement(){

        // use $compile service to create an instance of the directive
        // that we can test against
        element = $compile('<my-directive></my-directive>')($scope);

        // manually update scope
        $scope.$digest(); 
    }


    it("defines a 'lastScan' property", function() {

        compileElement();

        // trigger paste event
        element.triggerHandler('paste');

        // angular doesn't know about paste event so need
        // to manually update scope
        $scope.$digest();

        // immediately call $timeout callback
        // thus removing any asynchronous awkwardness
        $timeout.flush();

        // assert that directive has added property to the scope
        expect($scope.lastScan).toBeDefined();
    });
});

Upvotes: 1

Related Questions