Search code examples
angularjsprotractorangularjs-ngmock

Flush $timeout in protractor


I'm writing test using protractor and it always waits when $timeout will finished.

If I use ignoreSynchronization = true; it stops to wait and test runs ahead. But for my test I should set back ignoreSynchronization = false;. And when I set it to false, protractor stops and begin to wait for previous $timeout will finished.

I use $timeout for notification window and use this window to show validation errors. Currently I'm testing validation and it makes test extremely slow.

So the solution with ingnoreSynchronization = true is not compatible for me.

I have tried to $timeout.flush() but it cause an error $timeout.flush is not a function

I tried to use ngMock but am not sure is it possible to use it with protractor.

Does somebody resolve this issue?


Solution

  • I had the same exact issue. We are using timeouts on our notification UI and it was pausing the app every time we displayed a notifications till it dismissed itself. This worked for us:

    Protractor allows you to inject modules from your tests. So what we did was move our timeout duration argument into a constant, that could be set to 0 when running protractor tests.

    In your module:

    .constant('NOTIFICATION_CONSTANTS', {
      TIMEOUT_DURATION: 5000
    })
    
    .controller('NotificationController', function($scope, NOTIFICATION_CONSTANTS) 
    {
      $scope.showNotification = function() {
        $timeout(function() { hideNotification(); }, NOTIFICATION_CONSTANTS.TIMEOUT_DURATION)
      };
    })
    

    in your protractor test:

    ...
    beforeAll(function() {
      browser.addMockModule('testConfig', function() {
        angular.module('testConfig', []).run(function(NOTIFICATION_CONSTANTS) {
          NOTIFICATION_CONSTANTS.TIMEOUT_DURATION = 0;
        });
      });
    });
    ...
    

    It wont dismiss all $timeouts by default, but if they're created by you and you know which ones you want to dismiss you can target them like this.