Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 6370b07
Showing
26 changed files
with
15,972 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
node_modules | ||
lib-cov | ||
.DS_Store | ||
protractor-spec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"curly": true, | ||
"eqeqeq": true, | ||
"immed": true, | ||
"latedef": true, | ||
"laxcomma": true, | ||
"newcap": true, | ||
"noarg": true, | ||
"sub": true, | ||
"undef": true, | ||
"unused": true, | ||
"boss": true, | ||
"eqnull": true, | ||
"node": true | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
/* global document, window, angular */ | ||
/* jshint eqeqeq: false */ | ||
|
||
/** | ||
* All scripts to be run on the client via executeAsyncScript or | ||
* executeScript should be put here. These scripts are transmitted over | ||
* the wire using their toString representation, and cannot reference | ||
* external variables. They can, however use the array passed in to | ||
* arguments. Instead of params, all functions on clientSideScripts | ||
* should list the arguments array they expect. | ||
*/ | ||
var clientSideScripts = module.exports = {}; | ||
|
||
/** | ||
* Wait until Angular has finished rendering and has | ||
* no outstanding $http calls before continuing. | ||
* | ||
* arguments[0] {string} The selector housing an ng-app | ||
* arguments[1] {function} callback | ||
*/ | ||
clientSideScripts.waitForAngular = function() { | ||
var el = document.querySelector(arguments[0]); | ||
var callback = arguments[1]; | ||
angular.element(el).injector().get('$browser'). | ||
notifyWhenNoOutstandingRequests(callback); | ||
}; | ||
|
||
/** | ||
* Find an element in the page by their angular binding. | ||
* | ||
* arguments[0] {string} The binding, e.g. {{cat.name}}. | ||
* | ||
* @return {WebElement} The element containing the binding. | ||
*/ | ||
clientSideScripts.findBinding = function() { | ||
var bindings = document.getElementsByClassName('ng-binding'); | ||
var matches = []; | ||
var binding = arguments[0]; | ||
for (var i = 0; i < bindings.length; ++i) { | ||
var bindingName = angular.element(bindings[i]).data().$binding[0].exp || | ||
angular.element(bindings[i]).data().$binding; | ||
if (bindingName.indexOf(binding) != -1) { | ||
matches.push(bindings[i]); | ||
} | ||
} | ||
return matches[0]; // We can only return one with webdriver.findElement. | ||
}; | ||
|
||
/** | ||
* Find a list of elements in the page by their angular binding. | ||
* | ||
* arguments[0] {string} The binding, e.g. {{cat.name}}. | ||
* | ||
* @return {Array.<WebElement>} The elements containing the binding. | ||
*/ | ||
clientSideScripts.findBindings = function() { | ||
var bindings = document.getElementsByClassName('ng-binding'); | ||
var matches = []; | ||
var binding = arguments[0]; | ||
for (var i = 0; i < bindings.length; ++i) { | ||
var bindingName = angular.element(bindings[i]).data().$binding[0].exp || | ||
angular.element(bindings[i]).data().$binding; | ||
if (bindingName.indexOf(binding) != -1) { | ||
matches.push(bindings[i]); | ||
} | ||
} | ||
return matches; // Return the whole array for webdriver.findElements. | ||
}; | ||
|
||
/** | ||
* Find a row within an ng-repeat. | ||
* | ||
* arguments[0] {string} The text of the repeater, e.g. 'cat in cats'. | ||
* arguments[1] {number} The row index. | ||
* | ||
* @return {Element} The row element. | ||
*/ | ||
clientSideScripts.findRepeaterRow = function() { | ||
var repeater = arguments[0]; | ||
var index = arguments[1]; | ||
|
||
var rows = []; | ||
var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:']; | ||
for (var p = 0; p < prefixes.length; ++p) { | ||
var attr = prefixes[p] + 'repeat'; | ||
var repeatElems = document.querySelectorAll('[' + attr + ']'); | ||
attr = attr.replace(/\\/g, ''); | ||
for (var i = 0; i < repeatElems.length; ++i) { | ||
if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) { | ||
rows.push(repeatElems[i]); | ||
} | ||
} | ||
} | ||
return rows[index - 1]; | ||
}; | ||
|
||
/** | ||
* Find an element within an ng-repeat by its row and column. | ||
* | ||
* arguments[0] {string} The text of the repeater, e.g. 'cat in cats'. | ||
* arguments[1] {number} The row index. | ||
* arguments[2] {string} The column binding, e.g. '{{cat.name}}'. | ||
* | ||
* @return {Element} The element. | ||
*/ | ||
clientSideScripts.findRepeaterElement = function() { | ||
var matches = []; | ||
var repeater = arguments[0]; | ||
var index = arguments[1]; | ||
var binding = arguments[2]; | ||
|
||
var rows = []; | ||
var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:']; | ||
var i,p; | ||
for (p = 0; p < prefixes.length; ++p) { | ||
var attr = prefixes[p] + 'repeat'; | ||
var repeatElems = document.querySelectorAll('[' + attr + ']'); | ||
attr = attr.replace(/\\/g, ''); | ||
for (i = 0; i < repeatElems.length; ++i) { | ||
if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) { | ||
rows.push(repeatElems[i]); | ||
} | ||
} | ||
} | ||
var row = rows[index - 1]; | ||
var bindings = []; | ||
if (row.className.indexOf('ng-binding') != -1) { | ||
bindings.push(row); | ||
} | ||
var childBindings = row.getElementsByClassName('ng-binding'); | ||
for (i = 0; i < childBindings.length; ++i) { | ||
bindings.push(childBindings[i]); | ||
} | ||
for (i = 0; i < bindings.length; ++i) { | ||
var bindingName = angular.element(bindings[i]).data().$binding[0].exp || | ||
angular.element(bindings[i]).data().$binding; | ||
if (bindingName.indexOf(binding) != -1) { | ||
matches.push(bindings[i]); | ||
} | ||
} | ||
// We can only return one with webdriver.findElement. | ||
return matches[0]; | ||
}; | ||
|
||
/** | ||
* Find the elements in a column of an ng-repeat. | ||
* | ||
* arguments[0] {string} The text of the repeater, e.g. 'cat in cats'. | ||
* arguments[1] {string} The column binding, e.g. '{{cat.name}}'. | ||
* | ||
* @return {Array.<Element>} The elements in the column. | ||
*/ | ||
clientSideScripts.findRepeaterColumn = function() { | ||
var matches = []; | ||
var repeater = arguments[0]; | ||
var binding = arguments[1]; | ||
|
||
var rows = []; | ||
var p,i,j,k; | ||
var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:']; | ||
for (p = 0; p < prefixes.length; ++p) { | ||
var attr = prefixes[p] + 'repeat'; | ||
var repeatElems = document.querySelectorAll('[' + attr + ']'); | ||
attr = attr.replace(/\\/g, ''); | ||
for (i = 0; i < repeatElems.length; ++i) { | ||
if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) { | ||
rows.push(repeatElems[i]); | ||
} | ||
} | ||
} | ||
for (i = 0; i < rows.length; ++i) { | ||
var bindings = []; | ||
if (rows[i].className.indexOf('ng-binding') != -1) { | ||
bindings.push(rows[i]); | ||
} | ||
var childBindings = rows[i].getElementsByClassName('ng-binding'); | ||
for (k = 0; k < childBindings.length; ++k) { | ||
bindings.push(childBindings[k]); | ||
} | ||
for (j = 0; j < bindings.length; ++j) { | ||
var bindingName = angular.element(bindings[j]).data().$binding[0].exp || | ||
angular.element(bindings[j]).data().$binding; | ||
if (bindingName.indexOf(binding) != -1) { | ||
matches.push(bindings[j]); | ||
} | ||
} | ||
} | ||
return matches; | ||
}; | ||
|
||
/** | ||
* Find an input element by model name. | ||
* | ||
* arguments[0] {string} The model name. | ||
* | ||
* @return {Element} The first matching input element. | ||
*/ | ||
clientSideScripts.findInput = function() { | ||
var model = arguments[0]; | ||
var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:']; | ||
for (var p = 0; p < prefixes.length; ++p) { | ||
var selector = 'input[' + prefixes[p] + 'model="' + model + '"]'; | ||
var inputs = document.querySelectorAll(selector); | ||
if (inputs.length) { | ||
return inputs[0]; | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Find an select element by model name. | ||
* | ||
* arguments[0] {string} The model name. | ||
* | ||
* @return {Element} The first matching select element. | ||
*/ | ||
clientSideScripts.findSelect = function() { | ||
var model = arguments[0]; | ||
var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:']; | ||
for (var p = 0; p < prefixes.length; ++p) { | ||
var selector = 'select[' + prefixes[p] + 'model="' + model + '"]'; | ||
var inputs = document.querySelectorAll(selector); | ||
if (inputs.length) { | ||
return inputs[0]; | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Find an selected option element by model name. | ||
* | ||
* arguments[0] {string} The model name. | ||
* | ||
* @return {Element} The first matching input element. | ||
*/ | ||
clientSideScripts.findSelectedOption = function() { | ||
var model = arguments[0]; | ||
var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:']; | ||
for (var p = 0; p < prefixes.length; ++p) { | ||
var selector = | ||
'select[' + prefixes[p] + 'model="' + model + '"] option:checked'; | ||
var inputs = document.querySelectorAll(selector); | ||
if (inputs.length) { | ||
return inputs[0]; | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Tests whether the angular global variable is present on a page. Retries | ||
* in case the page is just loading slowly. | ||
* | ||
* arguments none. | ||
*/ | ||
clientSideScripts.testForAngular = function() { | ||
var attempts = arguments[0]; | ||
var callback = arguments[arguments.length - 1]; | ||
var check = function(n) { | ||
if (window.angular && window.angular.resumeBootstrap) { | ||
callback(true); | ||
} else if (n < 1) { | ||
callback(false); | ||
} else { | ||
window.setTimeout(function() {check(n - 1);}, 1000); | ||
} | ||
}; | ||
check(attempts); | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
var WdTractor = require('./wd_tractor'); | ||
var wd = require('wd'); | ||
|
||
wd.factory.WebDriver = WdTractor; | ||
|
||
module.exports = wd; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
var Args = require("vargs").Constructor; | ||
|
||
exports.varargs = function(args) { | ||
var fargs = new(Args)(args); | ||
// returning undefined instead of empty callback | ||
fargs.callback = fargs.callbackGiven()? fargs.callback : undefined; | ||
return fargs; | ||
}; |
Oops, something went wrong.