How can I make Protractor NOT wait for $timeout?

做~自己de王妃 提交于 2020-01-11 05:01:09

问题


I'm testing my angular application with Protractor. Once the user is logged in to my app, I set a $timeout to do some job in one hour (so if the user was logged-in in 13:00, the $timeout will run at 14:00). I keep getting these failures:

"Timed out waiting for Protractor to synchronize with the page after 20 seconds. Please see https://github.com/angular/protractor/blob/master/docs/faq.md. The following tasks were pending: - $timeout: function onTimeoutDone(){....."

I've read this timeouts page: https://github.com/angular/protractor/blob/master/docs/timeouts.md so I understand Protractor waits till the page is fully loaded which means he's waiting for the $timeout to complete...

How can I make Protractor NOT wait for that $timeout? I don't want to use:

browser.ignoreSynchronization = true;

Because then my tests will fail for other reasons (other angular components still needs the time to load...)


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/33340693/how-can-i-make-protractor-not-wait-for-timeout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!