問題描述
我正在使用 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?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!