Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
feat(protractor): add flag to stop protractor from tracking $timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
hankduan committed Oct 30, 2015
1 parent d7bb003 commit 2007f06
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 15 deletions.
8 changes: 7 additions & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,20 @@ You may need to insert a `browser.wait` condition to make sure the load
is complete before continuing.

How do I switch off an option in the CLI?
------------------------------------------------------------------------------
-----------------------------------------
i.e. `webdriver-manager update --chrome=false` does not work.
This has to do with the way `optimist` parses command line args. In order to pass a false value, do one of the following:

1) `webdriver-manager update --chrome=0`

2) `webdriver-manager update --no-chrome` (see https://github.com/substack/node-optimist#negate-fields)

Why does Protractor fail when I decorate $timeout?
--------------------------------------------------
Protractor tracks outstanding $timeouts by default, and reports them in the error message if Protractor fails to synchronize with Angular in time.

However, in order to do this Protractor needs to decorate $timeout. This means if your app decorates $timeout, you must turn off this behavior for Protractor. To do so pass in the 'untrackOutstandingTimeouts' flag.

I still have a question
-----------------------

Expand Down
7 changes: 7 additions & 0 deletions docs/referenceConf.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,13 @@ exports.config = {
// CAUTION: This will cause your tests to slow down drastically.
restartBrowserBetweenTests: false,

// Protractor will track outstanding $timeouts by default, and report them in
// the error message if Protractor fails to synchronize with Angular in time.
// In order to do this Protractor needs to decorate $timeout.
// CAUTION: If your app decorates $timeout, you must turn on this flag. This
// is false by default.
untrackOutstandingTimeouts: false,

// ---------------------------------------------------------------------------
// ----- The test framework --------------------------------------------------
// ---------------------------------------------------------------------------
Expand Down
45 changes: 33 additions & 12 deletions lib/protractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,11 @@ var buildElementHelper = function(ptor) {
* @param {string=} opt_baseUrl A base URL to run get requests against.
* @param {string=} opt_rootElement Selector element that has an ng-app in
* scope.
* @param {boolean=} opt_untrackOutstandingTimeouts Whether Protractor should
* stop tracking outstanding $timeouts.
*/
var Protractor = function(webdriverInstance, opt_baseUrl, opt_rootElement) {
var Protractor = function(webdriverInstance, opt_baseUrl, opt_rootElement,
opt_untrackOutstandingTimeouts) {
// These functions should delegate to the webdriver instance, but should
// wait for Angular to sync up before performing the action. This does not
// include functions which are overridden by protractor below.
Expand Down Expand Up @@ -216,6 +219,13 @@ var Protractor = function(webdriverInstance, opt_baseUrl, opt_rootElement) {
}
});

/**
* If true, Protractor will track outstanding $timeouts and report them in the
* error message if Protractor fails to synchronize with Angular in time.
* @private {boolean}
*/
this.trackOutstandingTimeouts_ = !opt_untrackOutstandingTimeouts;

/**
* Information about mock modules that will be installed during every
* get().
Expand Down Expand Up @@ -382,10 +392,15 @@ Protractor.prototype.waitForAngular = function(opt_description) {
var errMsg = 'Timed out waiting for Protractor to synchronize with ' +
'the page after ' + timeout + '. Please see ' +
'https://github.com/angular/protractor/blob/master/docs/faq.md';
var pendingTimeoutsPromise = self.executeScript_(
'return window.NG_PENDING_TIMEOUTS',
'Protractor.waitForAngular() - getting pending timeouts' + description
);
var pendingTimeoutsPromise;
if (self.trackOutstandingTimeouts_) {
pendingTimeoutsPromise = self.executeScript_(
'return window.NG_PENDING_TIMEOUTS',
'Protractor.waitForAngular() - getting pending timeouts' + description
);
} else {
pendingTimeoutsPromise = webdriver.promise.fulfilled({});
}
var pendingHttpsPromise = self.executeScript_(
clientSideScripts.getPendingHttpRequests,
'Protractor.waitForAngular() - getting pending https' + description,
Expand Down Expand Up @@ -518,14 +533,15 @@ Protractor.prototype.getRegisteredMockModules = function() {
* @private
*/
Protractor.prototype.addBaseMockModules_ = function() {
this.addMockModule('protractorBaseModule_', function() {
angular.module('protractorBaseModule_', []).
this.addMockModule('protractorBaseModule_', function(trackOutstandingTimeouts) {
var ngMod = angular.module('protractorBaseModule_', []).
config(['$compileProvider', function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(true);
}
}]).
config(['$provide', function($provide) {
}]);
if (trackOutstandingTimeouts) {
ngMod.config(['$provide', function($provide) {
$provide.decorator('$timeout', ['$delegate', function($delegate) {
var $timeout = $delegate;

Expand Down Expand Up @@ -567,7 +583,8 @@ Protractor.prototype.addBaseMockModules_ = function() {
return extendedTimeout;
}]);
}]);
});
}
}, this.trackOutstandingTimeouts_);
};

/**
Expand Down Expand Up @@ -1041,8 +1058,12 @@ Protractor.prototype.pause = function(opt_debugPort) {
*
* @param {webdriver.WebDriver} webdriver The configured webdriver instance.
* @param {string=} opt_baseUrl A URL to prepend to relative gets.
* @param {boolean=} opt_untrackOutstandingTimeouts Whether Protractor should
* stop tracking outstanding $timeouts.
* @return {Protractor}
*/
exports.wrapDriver = function(webdriver, opt_baseUrl, opt_rootElement) {
return new Protractor(webdriver, opt_baseUrl, opt_rootElement);
exports.wrapDriver = function(webdriver, opt_baseUrl, opt_rootElement,
opt_untrackOutstandingTimeouts) {
return new Protractor(webdriver, opt_baseUrl, opt_rootElement,
opt_untrackOutstandingTimeouts);
};
3 changes: 1 addition & 2 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ Runner.prototype.createBrowser = function(plugins) {
var driver = this.driverprovider_.getNewDriver();

var browser_ = protractor.wrapDriver(driver,
config.baseUrl, config.rootElement);
config.baseUrl, config.rootElement, config.untrackOutstandingTimeouts);

browser_.params = config.params;
if (plugins) {
Expand All @@ -202,7 +202,6 @@ Runner.prototype.createBrowser = function(plugins) {
}
var self = this;


browser_.ready =
driver.manage().timeouts().setScriptTimeout(config.allScriptsTimeout);

Expand Down
8 changes: 8 additions & 0 deletions scripts/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ executor.addCommandlineTest('node lib/cli.js spec/errorTest/slowHttpAndTimeoutCo
'*}'}
]);

executor.addCommandlineTest('node lib/cli.js spec/errorTest/slowHttpAndTimeoutConf.js ' +
'--untrackOutstandingTimeouts true')
.expectExitCode(1)
.expectErrors([
{message: 'The following tasks were pending[\\s\\S]*\\$http: \/slowcall'},
{message: '^((?!The following tasks were pending).)*$'}
]);

// Check ngHint plugin

executor.addCommandlineTest(
Expand Down

0 comments on commit 2007f06

Please sign in to comment.