如何让量角器不等待$ timeout?

时间:2015-10-26 07:40:19

标签: javascript angularjs selenium protractor angularjs-e2e

我正在用Protractor测试我的角应用程序。 一旦用户登录到我的应用程序,我设置$ timeout以在一小时内完成某项工作(因此,如果用户在13:00登录,则$ timeout将在14:00运行)。 我一直在接受这些失败:

"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(){....."

我已阅读此超时页面:https://github.com/angular/protractor/blob/master/docs/timeouts.md 所以我理解量角器等待页面完全加载,这意味着他等待$ timeout完成...

如何让量角器不等待$ timeout? 我不想使用:

browser.ignoreSynchronization = true;

因为那时我的测试会因其他原因而失败(其他角度组件仍然需要加载时间......)

2 个答案:

答案 0 :(得分:3)

解决方案是刷新活动超时(as @MBielski mentioned it in comments),但原始刷新方法本身仅在anuglar-mocks中可用。要直接使用角度模拟,您必须将其作为<script>标记包含在页面上,并且您还必须处理它创建的所有覆盖,它会产生许多副作用。通过听取创建的任何超时,然后根据需要重置它们,我能够在不使用角度模拟的情况下重新创建flush。

例如,如果您的Angular应用中有超时:

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

测试将如下所示:

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);
});

这有点实验性,我不确定它是否适用于您的情况。通过将browser.addMockModule移动到单独的node.js模块,也可以简化此代码。如果您想要删除短暂超时(如100毫秒),也可能会出现问题,它可以取消当前运行的Angular进程,因此测试会中断。

答案 1 :(得分:0)

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.