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.