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

Tam*_*hen 7 javascript selenium angularjs angularjs-e2e protractor

我用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(){....."
Run Code Online (Sandbox Code Playgroud)

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

如何让Protractor不等待$ timeout?我不想用:

browser.ignoreSynchronization = true;
Run Code Online (Sandbox Code Playgroud)

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

Mic*_*nov 3

解决方案是刷新活动超时(正如 @MBielski 在评论中提到的那样),但原始刷新方法本身仅在 anuglar-mocks 中可用。要直接使用 Angular-Mocks,您必须将其作为<script>标签包含在页面上,并且您还必须处理它创建的所有覆盖,它会产生很多副作用。我能够在不使用角度模拟的情况下重新创建刷新,方法是监听创建的任何超时,然后根据需要重置它们。

例如,如果您的 Angular 应用程序超时:

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

测试将如下所示:

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);
});
Run Code Online (Sandbox Code Playgroud)

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