Simulate the passage of time in protractor?

2020-03-04 08:41发布

I have a few spots where things happen in the UI on a delay using $timeout or $interval. Here's a simplified example:

Controller code:

$timeout(function() {
    $scope.showElement = true;
}, 10000);

HTML:

<div id="myElement" ng-show="showElement"></div>

I want to be able to create an end-to-end Protractor test that tests whether #myElement gets displayed after a 10 second wait. The only way I have found to do this is to call browser.sleep(10000), which results in an actual 10-second delay in my test. This works, but these pauses add up add up and significantly increase the duration of my tests. Imagine a situation where you wanted to test whether a modal pops up after 30 minutes of inactivity.

Is there a way to simulate the passage of a specific amount of time, similar to $timeout.flush() in a jasmine test?

2条回答
Juvenile、少年°
2楼-- · 2020-03-04 08:44

You can decorate $timeout and $interval to override the delay supplied to them:

lower-wait-time.js

exports.module = function() {
    angular.module('lowerWaitTimeDecorator', [])
    .config(function($provide) {
        $provide.decorator('$timeout', function($delegate) {
            return function() {
                // The second argument is the delay in ms
                arguments[1] = arguments[1] / 10;
                return $delegate.apply(this, arguments);
            };
        });
    })
};

Usage

beforeAll(function() {
    var lowerWaitTime = require('lower-wait-time');
    browser.addMockModule('lowerWaitTimeDecorator', lowerWaitTime.module);
});

afterAll(function() {
    browser.removeMockModule('lowerWaitTimeDecorator');
});

it('My-sped-up-test', function() {

});
查看更多
迷人小祖宗
3楼-- · 2020-03-04 09:03

You could do this potentially using async.whilst. The idea is keep on looking for the element until the timeout is reached. If the element is found BEFORE timeout reaches or if element is NOT found within the timeout, test fails otherwise it passes. I haven't tested this but you get the idea. For example,

var driver = browser.driver,
 wd = browser.wd,
 async = require('async'),
 start = Date.now(),
 found = false,
 diff;
 async.whilst(
      function() {
          var diff = Date.now() - start;
          return diff <= 10000 && !found;
      },
      function(callback) {
         driver.findElement(wd.By.id('myElement')).then(function() {
              found = true;
              callback();
           },function(err) {
            found = false;
            callback();
         });
      },
      function (err) {
          var isTesrPassed = !err && found && diff>=10000;
          assertTrue(isTestPassed, 'element visibility test failed');
      }
 );
查看更多
登录 后发表回答