How can I make Protractor NOT wait for $timeout? How can I make Protractor NOT wait for $timeout? selenium selenium

How can I make Protractor NOT wait for $timeout?


The solution will be to flush active timeouts (as @MBielski mentioned it in comments), but original flush method itself is available only in anuglar-mocks. To use angular-mocks directly you will have to include it on the page as a <script> tag and also you'll have to deal with all overrides it creates, it produces a lot of side effects. I was able to re-create flush without using angular-mocks by listening to any timeouts that get created and then reseting them on demand.

For example, if you have a timeout in your Angular app:

$timeout(function () {    alert('Hello World');}, 10000); // say hello in 10 sec

The test will look like:

it('should reset timeouts', function () {    browser.addMockModule('e2eFlushTimeouts', function () {        angular        .module('e2eFlushTimeouts', [])        .run(function ($browser) {            // store all created timeouts            var timeouts = [];            // listen to all timeouts created by overriding            // a method responsible for that            var originalDefer = $browser.defer;            $browser.defer = function (fn, delay) {                // originally it returns timeout id                var timeoutId = originalDefer.apply($browser, arguments);                // store it to be able to remove it later                timeouts.push({ id: timeoutId, delay: delay });                // preserve original behavior                return timeoutId;            };            // compatibility with original method            $browser.defer.cancel = originalDefer.cancel;            // create a global method to flush timeouts greater than @delay            // call it using browser.executeScript()            window.e2eFlushTimeouts = function (delay) {                timeouts.forEach(function (timeout) {                    if (timeout.delay >= delay) {                        $browser.defer.cancel(timeout.id);                    }                });            };        });    });    browser.get('example.com');    // do test stuff    browser.executeScript(function () {        // flush everything that has a delay more that 6 sec        window.e2eFlushTimeouts(6000);     });    expect(something).toBe(true);});

It's kinda experimental, I am not sure if it will work for your case. This code can also be simplified by moving browser.addMockModule to a separate node.js module. Also there may be problems if you'd want to remove short timeouts (like 100ms), it can cancel currently running Angular processes, therefore the test will break.


The solution is to use interceptors and modify the http request which is getting timeout and set custom timeout to some milliseconds(your desired) to that http request so that after sometime long running http request will get closed(because of new timeout) and then you can test immediate response.

This is working well and promising.