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

Commit be236e7

Browse files
committed
feat(debugging): use custom messages when executing scripts to improve stack traces
Now, instead of asynchronous events during executeScript all being described as `WebDriver.executeScript`, they have their own custom messages. The schedule shown when debugging will be more informative, as in the example below: ``` -- WebDriver control flow schedule |- waiting for debugger to attach |--- at null.<anonymous> (/Users/ralphj/protractor/debugging/failure_spec.js:37:13) |- WebDriver.navigate().to(data:text/html,<html></html>) |--- at null.<anonymous> (/Users/ralphj/protractor/debugging/failure_spec.js:38:13) |- Protractor.get(http://localhost:8081/index.html#/form) - reset url |--- at null.<anonymous> (/Users/ralphj/protractor/debugging/failure_spec.js:38:13) |- Timed out waiting for page to load after 10000ms |--- at null.<anonymous> (/Users/ralphj/protractor/debugging/failure_spec.js:38:13) |- Protractor.get(http://localhost:8081/index.html#/form) - test for angular |--- at null.<anonymous> (/Users/ralphj/protractor/debugging/failure_spec.js:38:13) |- Protractor.get(http://localhost:8081/index.html#/form) - add mock module |--- at null.<anonymous> (/Users/ralphj/protractor/debugging/failure_spec.js:38:13) |- Protractor.get(http://localhost:8081/index.html#/form) - resume bootstrap |--- at null.<anonymous> (/Users/ralphj/protractor/debugging/failure_spec.js:38:13) |- Protractor.waitForAngular() |--- at null.<anonymous> (/Users/ralphj/protractor/debugging/failure_spec.js:42:21) ```
1 parent c68dcdc commit be236e7

File tree

1 file changed

+81
-21
lines changed

1 file changed

+81
-21
lines changed

lib/protractor.js

+81-21
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,54 @@ var Protractor = function(webdriverInstance, opt_baseUrl, opt_rootElement) {
10971097
this.addBaseMockModules_();
10981098
};
10991099

1100+
/**
1101+
* The same as {@code webdriver.WebDriver.prototype.executeScript},
1102+
* but with a customized description for debugging.
1103+
*
1104+
* @private
1105+
* @param {!(string|Function)} script The script to execute.
1106+
* @param {string} description A description of the command for debugging.
1107+
* @param {...*} var_args The arguments to pass to the script.
1108+
* @return {!webdriver.promise.Promise.<T>} A promise that will resolve to the
1109+
* scripts return value.
1110+
* @template T
1111+
*/
1112+
Protractor.prototype.executeScript_ = function(script, description) {
1113+
if (typeof script === 'function') {
1114+
script = 'return (' + script + ').apply(null, arguments);';
1115+
}
1116+
1117+
return this.driver.schedule(
1118+
new webdriver.Command(webdriver.CommandName.EXECUTE_SCRIPT).
1119+
setParameter('script', script).
1120+
setParameter('args', Array.prototype.slice.call(arguments, 2)),
1121+
description);
1122+
};
1123+
1124+
/**
1125+
* The same as {@code webdriver.WebDriver.prototype.executeAsyncScript},
1126+
* but with a customized description for debugging.
1127+
*
1128+
* @private
1129+
* @param {!(string|Function)} script The script to execute.
1130+
* @param {string} description A description for debugging purposes.
1131+
* @param {...*} var_args The arguments to pass to the script.
1132+
* @return {!webdriver.promise.Promise.<T>} A promise that will resolve to the
1133+
* scripts return value.
1134+
* @template T
1135+
*/
1136+
Protractor.prototype.executeAsyncScript_ =
1137+
function(script, description) {
1138+
if (typeof script === 'function') {
1139+
script = 'return (' + script + ').apply(null, arguments);';
1140+
}
1141+
return this.driver.schedule(
1142+
new webdriver.Command(webdriver.CommandName.EXECUTE_ASYNC_SCRIPT).
1143+
setParameter('script', script).
1144+
setParameter('args', Array.prototype.slice.call(arguments, 2)),
1145+
description);
1146+
};
1147+
11001148
/**
11011149
* Instruct webdriver to wait until Angular has finished rendering and has
11021150
* no outstanding $http calls before continuing.
@@ -1108,12 +1156,14 @@ Protractor.prototype.waitForAngular = function() {
11081156
if (this.ignoreSynchronization) {
11091157
return webdriver.promise.fulfilled();
11101158
}
1111-
return this.driver.executeAsyncScript(
1112-
clientSideScripts.waitForAngular, this.rootEl).then(function(browserErr) {
1113-
if (browserErr) {
1114-
throw 'Error while waiting for Protractor to ' +
1115-
'sync with the page: ' + JSON.stringify(browserErr);
1116-
}
1159+
return this.executeAsyncScript_(
1160+
clientSideScripts.waitForAngular, 'Protractor.waitForAngular()',
1161+
this.rootEl).
1162+
then(function(browserErr) {
1163+
if (browserErr) {
1164+
throw 'Error while waiting for Protractor to ' +
1165+
'sync with the page: ' + JSON.stringify(browserErr);
1166+
}
11171167
}).then(null, function(err) {
11181168
var timeout;
11191169
if (/asynchronous script timeout/.test(err.message)) {
@@ -1242,20 +1292,24 @@ Protractor.prototype.get = function(destination, opt_timeout) {
12421292

12431293
destination = this.baseUrl.indexOf('file://') === 0 ?
12441294
this.baseUrl + destination : url.resolve(this.baseUrl, destination);
1295+
var msg = function(str) {
1296+
return 'Protractor.get(' + destination + ') - ' + str;
1297+
};
12451298

12461299
if (this.ignoreSynchronization) {
12471300
return this.driver.get(destination);
12481301
}
12491302

12501303
this.driver.get(this.resetUrl);
1251-
this.driver.executeScript(
1304+
this.executeScript_(
12521305
'window.name = "' + DEFER_LABEL + '" + window.name;' +
1253-
'window.location.replace("' + destination + '");');
1306+
'window.location.replace("' + destination + '");',
1307+
msg('reset url'));
12541308

12551309
// We need to make sure the new url has loaded before
12561310
// we try to execute any asynchronous scripts.
12571311
this.driver.wait(function() {
1258-
return self.driver.executeScript('return window.location.href;').
1312+
return self.executeScript_('return window.location.href;', msg('get url')).
12591313
then(function(url) {
12601314
return url !== self.resetUrl;
12611315
}, function(err) {
@@ -1271,11 +1325,12 @@ Protractor.prototype.get = function(destination, opt_timeout) {
12711325
}
12721326
});
12731327
}, timeout,
1274-
'Timed out waiting for page to load after ' + timeout + 'ms');
1328+
'waiting for page to load for ' + timeout + 'ms');
12751329

12761330
// Make sure the page is an Angular page.
1277-
self.driver.executeAsyncScript(clientSideScripts.testForAngular,
1278-
Math.floor(timeout / 1000)).
1331+
self.executeAsyncScript_(clientSideScripts.testForAngular,
1332+
msg('test for angular'),
1333+
Math.floor(timeout / 1000)).
12791334
then(function(angularTestResult) {
12801335
var hasAngular = angularTestResult[0];
12811336
if (!hasAngular) {
@@ -1294,16 +1349,18 @@ Protractor.prototype.get = function(destination, opt_timeout) {
12941349
var mockModule = this.mockModules_[i];
12951350
var name = mockModule.name;
12961351
moduleNames.push(name);
1297-
var executeScriptArgs = [mockModule.script].concat(mockModule.args);
1298-
this.driver.executeScript.apply(this, executeScriptArgs).
1352+
var executeScriptArgs = [mockModule.script, msg('add mock module ' + name)].
1353+
concat(mockModule.args);
1354+
this.executeScript_.apply(this, executeScriptArgs).
12991355
then(null, function(err) {
13001356
throw 'Error while running module script ' + name +
13011357
': ' + err.message;
13021358
});
13031359
}
13041360

1305-
return this.driver.executeScript(
1361+
return this.executeScript_(
13061362
'angular.resumeBootstrap(arguments[0]);',
1363+
msg('resume bootstrap'),
13071364
moduleNames);
13081365
};
13091366

@@ -1325,9 +1382,11 @@ Protractor.prototype.refresh = function(opt_timeout) {
13251382
return self.driver.navigate().refresh();
13261383
}
13271384

1328-
return self.driver.executeScript('return window.location.href').then(function(href) {
1329-
return self.get(href, timeout);
1330-
});
1385+
return self.executeScript_(
1386+
'return window.location.href',
1387+
'Protractor.refresh() - getUrl').then(function(href) {
1388+
return self.get(href, timeout);
1389+
});
13311390
};
13321391

13331392
/**
@@ -1349,8 +1408,8 @@ Protractor.prototype.navigate = function() {
13491408
*/
13501409
Protractor.prototype.setLocation = function(url) {
13511410
this.waitForAngular();
1352-
return this.driver.executeScript(clientSideScripts.setLocation, this.rootEl, url)
1353-
.then(function(browserErr) {
1411+
return this.executeScript_(clientSideScripts.setLocation,
1412+
'Protractor.setLocation()', this.rootEl, url).then(function(browserErr) {
13541413
if (browserErr) {
13551414
throw 'Error while navigating to \'' + url + '\' : ' +
13561415
JSON.stringify(browserErr);
@@ -1363,7 +1422,8 @@ Protractor.prototype.setLocation = function(url) {
13631422
*/
13641423
Protractor.prototype.getLocationAbsUrl = function() {
13651424
this.waitForAngular();
1366-
return this.driver.executeScript(clientSideScripts.getLocationAbsUrl, this.rootEl);
1425+
return this.executeScript_(clientSideScripts.getLocationAbsUrl,
1426+
'Protractor.getLocationBasUrl()', this.rootEl);
13671427
};
13681428

13691429
/**

0 commit comments

Comments
 (0)