2017-03-17 30 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; 
     }]); 
    }); 
});