问题描述
我正在使用 Protractor 测试我的 Angular 应用程序.一旦用户登录到我的应用程序,我设置一个 $timeout 在一小时内完成一些工作(所以如果用户在 13:00 登录,$timeout 将在 14:00 运行).我不断收到这些失败:
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(){....."
我已阅读此超时页面:https://github.com/angular/protractor/blob/master/docs/timeouts.md所以我知道量角器会等到页面完全加载,这意味着他正在等待 $timeout 完成......
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...
如何让 Protractor 不等待 $timeout?我不想使用:
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...)
推荐答案
解决方案是刷新活动超时(@MBielski 在评论中提到它),但原始刷新方法本身仅在 anuglar-mocks 中可用.要直接使用 angular-mocks,您必须将其作为 <script>
标记包含在页面中,并且您必须处理它创建的所有覆盖,它会产生很多副作用.通过侦听创建的任何超时,然后按需重置它们,我能够在不使用 angular-mocks 的情况下重新创建刷新.
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.
例如,如果您的 Angular 应用程序超时:
For example, if you have a timeout in your Angular app:
$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 进程,因此测试会中断.
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.
这篇关于如何让 Protractor 不等待 $timeout?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!