2017-03-17 35 views
11

問題描述:規範的方法來調試量角器對角同步問題

而在量角器終端到終端的測試中打開我們的應用程序的一個頁面最近,我們得到這個臭名昭著的錯誤:

失敗:超時等待異步Angular任務在50秒後完成。這可能是因爲當前頁面不是Angular應用程序。

這發生在我們的測試中的一個browser.get("/some/page/");電話:

describe("Test", function() { 
    beforeEach(function() { 
     browser.get("/some/page/"); 
    }); 

    it("should test something", function() { 
     // ... 
    }); 
)}; 

而且,什麼是奇怪我們的情況下,該錯誤沒有任何其他網頁在我們斜網拋出應用 - 量角器與Angular同步,沒有任何問題。 ng-app位置明智的事情是在所有頁面的相同 - ng-app是根html標籤定義:

<html class="ng-scope" lang="en-us" ng-app="myApp" ng-strict-di=""> 

的行爲是一致的 - 我們每次導航到該頁面browser.get()時間,我們得到這個錯誤。任何時候我們導航到我們的應用程序中的任何其他頁面,同步工作。

請注意,當然,我們可以關閉此頁面的同步並將其視爲非角度,但這隻能視爲解決方法。

的問題:

還有什麼可以引起量角器對角同步失敗?我們應該檢查什麼?

而且,一般來說,推薦使用哪種方法來調試量角器中的同步問題?

使用目前最新的Protractor 5.5.1,Angular 1.5.6。

+0

我想這是同步問題。 '的https:// github.com /角度/量角器/斑點/主/文檔/ timeouts.md#如何到禁用等待換angular'。他們告訴的解決方案與關閉同步或者可能使用'driver.browser.get()'而不是'browser.get()'相同。 –

+0

@KishanPatel謝謝,但正如我在問題中提到的,我明白我們可以關閉同步並將頁面視爲非角度 - 這是一種解決方法,它會工作,但我們正在嘗試找出爲什麼同步不適用於此特定頁面和一般準則來調試此類問題。 – alecxe

+0

你的錯誤清楚地表明它可以同步,因爲Angular,並且有兩個原因會發生'$ http'和'$ timeout' - 量角器將等待這兩個服務完成。如果它是由'$ timeout'引起的,那麼你應該簡單地用'$ interval'替換它,而對於'$ http',除非你想寫一個XHR服務並用它代替'$ http',否則沒有解決方法。 – maurycy

回答

6

好了,這個問題吸引了我,所以我想出瞭如何確定哪些量角器一個綱領性的解決方案正在等待:

var _injector = angular.element(document).injector(); 
var _$browser = _injector.get('$browser'); 
var _$http = _injector.get('$http'); 
var pendingTimeout = true; 

//this is actually method that protractor is using while waiting to sync 
//if callback is called immediately that means there are no $timeout or $http calls 
_$browser.notifyWhenNoOutstandingRequests(function callback() { 
    pendingTimeout = false 
}); 

setTimeout(function() { 
    //this is to differentiate between $http and timeouts from the "notifyWhenNoOutstandingRequests" method 
    if (_$http.pendingRequests.length) { 
    console.log('Outstanding $http requests', _$http.pendingRequests.length) 
    } else if (pendingTimeout) { 
    console.log('Outstanding timeout') 
    } else { 
    console.log('All fine in Angular, it has to be something else') 
    } 
}, 100) 

在這裏,在plunker http://plnkr.co/edit/O0CkpnsnUuwEAV8I2Jil?p=preview您可以用超時和實驗$ http呼叫,我的延遲端點將等待10秒鐘才能解決通話,希望這會對您有所幫助

1

我同意@maurycy的問題是$ http/$ timeout相關的問題。簡單的解決方法是通常與$間隔更換$超時作爲記錄在這裏:https://github.com/angular/protractor/blob/master/docs/timeouts.md

建議: merge these sane defaults: allScriptsTimeout: 60000, // 1 minute jasmineNodeOpts: { defaultTimeoutInterval: 300000 // 5 minutes. Allows for 5 commands spanning the full synchronization timeout. }

如果你想找到$ HTTP/$超時的罪魁禍首,我會用角裝飾應用圍繞這些服務的定製邏輯。這也是模擬角色服務訪問第三方服務的好方法。 https://docs.angularjs.org/guide/decorators

//DISCLOSURE: Unlinted & Untested. 
beforeAll(() => { 
    browser.addMockModule('culpritMock',() => { 
    angular.module('culpritMock', []) 
     .config(['$httpProvider', 
     $httpProvider => $httpProvider.interceptors.push('httpCounterInterceptor') 
     ]) 
     .factory('httpCounterInterceptor', ['$q', '$window', ($q, $window) => { 
     if ($window.httpCounterInterceptor == null) { 
      $window.httpCounterInterceptor = {}; 
     } 
     return { 
      request: config => { 
      $window.httpCounterInterceptor[config.url] = 'started'; 
      return config; 
      }, 
      response: response => { 
      $window.httpCounterInterceptor[response.config.url] = 'completed'; 
      return response; 
      }, 
      responseError: rejection => { 
      $window.httpCounterInterceptor[rejection.config.url] = 'error'; 
      return $q.reject(rejection); 
      } 
     }; 
     }]) 
     .decorator('$timeout', ['$delegate', $delegate => { 
     const originalTimeout = $delegate; 
     function modifiedTimeout() { 
      console.log(arguments); 
     return originalTimeout.apply(null, arguments); 
     } 
     modifiedTimeout.cancel = function(promise) { 
      return $delegate.cancel(promise); 
     } 
     return modifiedTimeout; 
     }]); 
    }); 
});