protractor
Advanced tools
Comparing version 0.1.2 to 0.1.3
{ | ||
"name" : "protractor", | ||
"description" : "End to End test helpers for Angular.", | ||
"description" : "Webdriver E2E test wrapper for Angular.", | ||
"homepage" : "https://github.com/juliemr/protractor", | ||
@@ -15,3 +15,3 @@ "keywords" : ["angular", "test", "testing", "webdriver", "webdriverjs", "selenium"], | ||
"main" : "protractor.js", | ||
"version" : "0.1.2" | ||
"version" : "0.1.3" | ||
} |
@@ -1,91 +0,147 @@ | ||
var url = require('url'); | ||
var util = require('util'); | ||
var webdriver = require('selenium-webdriver'); | ||
exports.wrapDriver = function(webdriver) { | ||
// should this delegate to all functions on the webdriver? Should it | ||
// actually modify the input driver? | ||
var driver = webdriver, | ||
moduleNames = [], | ||
moduleScripts = []; | ||
var DEFER_LABEL = 'NG_DEFER_BOOTSTRAP!'; | ||
/** | ||
* @param {webdriver.WebDriver} webdriver | ||
* @constructor | ||
*/ | ||
var Protractor = function(webdriver) { | ||
this.driver = webdriver; | ||
var DEFER_LABEL = 'NG_DEFER_BOOTSTRAP!'; | ||
this.moduleNames_ = []; | ||
var waitForAngular = function() { | ||
return driver.executeAsyncScript(function() { | ||
var callback = arguments[arguments.length - 1]; | ||
angular.element(document.body).injector().get('$browser'). | ||
notifyWhenNoOutstandingRequests(callback); | ||
}); | ||
}; | ||
this.moduleScripts_ = []; | ||
}; | ||
return { | ||
findElement: function(locator, varArgs) { | ||
waitForAngular(); | ||
return driver.findElement(locator, varArgs); | ||
}, | ||
/** | ||
* Instruct webdriver to wait until Angular has finished rendering and has | ||
* no outstanding $http calls before continuing. | ||
* | ||
* @return {!webdriver.promise.Promise} A promise that will resolve to the | ||
* scripts return value. | ||
*/ | ||
Protractor.prototype.waitForAngular = function() { | ||
return this.driver.executeAsyncScript(function() { | ||
var callback = arguments[arguments.length - 1]; | ||
angular.element(document.body).injector().get('$browser'). | ||
notifyWhenNoOutstandingRequests(callback); | ||
}); | ||
}; | ||
/** | ||
* @param <string> name | ||
* @param <Function|string> script | ||
*/ | ||
addMockModule: function(name, script) { | ||
moduleNames.push(name); | ||
moduleScripts.push(script); | ||
}, | ||
/** | ||
* See webdriver.WebDriver.findElement | ||
* | ||
* Waits for Angular to finish rendering before searching for elements. | ||
*/ | ||
Protractor.prototype.findElement = function(locator, varArgs) { | ||
this.waitForAngular(); | ||
if (locator.findOverride) { | ||
return locator.findOverride(this.driver); | ||
} | ||
return this.driver.findElement(locator, varArgs); | ||
}; | ||
clearMockModules: function() { | ||
moduleNames = []; | ||
moduleScripts = []; | ||
}, | ||
/** | ||
* Add a module to load before Angular whenever Protractor.get is called. | ||
* Modules will be registered after existing modules already on the page, | ||
* so any module registered here will override preexisting modules with the same | ||
* name. | ||
* | ||
* @param {!string} name The name of the module to load or override. | ||
* @param {!string|Function} script The JavaScript to load the module. | ||
*/ | ||
Protractor.prototype.addMockModule = function(name, script) { | ||
this.moduleNames_.push(name); | ||
this.moduleScripts_.push(script); | ||
}; | ||
/** | ||
* Usage: | ||
* protractor.addMockModule(moduleA); | ||
* protractor.addMockModule(moduleB); | ||
* protractor.get('foo.com'); | ||
*/ | ||
get: function(destination) { | ||
driver.get('about:blank'); | ||
driver.executeScript('window.name += "' + DEFER_LABEL + '";' + | ||
'window.location.href = "' + destination + '"'); | ||
// At this point, Angular will pause for us, until angular.resumeBootstrap is called. | ||
/** | ||
* Clear the list of registered mock modules. | ||
*/ | ||
Protractor.prototype.clearMockModules = function() { | ||
this.moduleNames_ = []; | ||
this.moduleScripts_ = []; | ||
}; | ||
for (var i = 0; i < moduleScripts.length; ++i) { | ||
driver.executeScript(moduleScripts[i]); // Should this be async? | ||
} | ||
/** | ||
* See webdriver.WebDriver.get | ||
* | ||
* Navigate to the given destination and loads mock modules before | ||
* Angular. | ||
*/ | ||
Protractor.prototype.get = function(destination) { | ||
this.driver.get('about:blank'); | ||
this.driver.executeScript('window.name += "' + DEFER_LABEL + '";' + | ||
'window.location.href = "' + destination + '"'); | ||
// At this point, Angular will pause for us, until angular.resumeBootstrap | ||
// is called. | ||
driver.executeAsyncScript(function() { | ||
var callback = arguments[arguments.length - 1]; | ||
// Continue to bootstrap Angular. | ||
angular.resumeBootstrap(arguments[0]); | ||
callback(); | ||
}, moduleNames); | ||
} | ||
}; | ||
for (var i = 0; i < this.moduleScripts_.length; ++i) { | ||
this.driver.executeScript(this.moduleScripts_[i]); | ||
} | ||
this.driver.executeAsyncScript(function() { | ||
var callback = arguments[arguments.length - 1]; | ||
// Continue to bootstrap Angular. | ||
angular.resumeBootstrap(arguments[0]); | ||
callback(); | ||
}, this.moduleNames_); | ||
}; | ||
/** | ||
* Create a new instance of Protractor by wrapping a webdriver instance. | ||
* | ||
* @param {webdriver.WebDriver} webdriver The configured webdriver instance. | ||
*/ | ||
exports.wrapDriver = function(webdriver) { | ||
return new Protractor(webdriver); | ||
}; | ||
/** | ||
* Locators. | ||
*/ | ||
var ProtractorBy = function() {} | ||
var WebdriverBy = function() {}; | ||
WebdriverBy.prototype = require('selenium-webdriver').By; | ||
/** | ||
* webdriver's By is an enum of locator functions, so we must set it to | ||
* a prototype before inheriting from it. | ||
*/ | ||
WebdriverBy.prototype = webdriver.By; | ||
util.inherits(ProtractorBy, WebdriverBy); | ||
ProtractorBy.prototype.binding = function() { | ||
/** | ||
* Usage: | ||
* <span>{{status}}</span> | ||
* var status = ptor.findElement(protractor.By.binding('{{status}}')); | ||
* | ||
* Note: This ignores parent element restrictions if called with | ||
* WebElement.findElement. | ||
*/ | ||
ProtractorBy.prototype.binding = function(bindingDescriptor) { | ||
return { | ||
using: 'js', | ||
value: function() { | ||
var bindings = document.getElementsByClassName('ng-binding'); | ||
var matches = []; | ||
var binding = arguments[0]; | ||
for (var i = 0; i < bindings.length; ++i) { | ||
if (angular.element(bindings[i]).data().$binding[0].exp == binding) { | ||
matches.push(bindings[i]); | ||
findOverride: function(driver) { | ||
return driver.findElement(webdriver.By.js(function() { | ||
var bindings = document.getElementsByClassName('ng-binding'); | ||
var matches = []; | ||
var binding = arguments[0]; | ||
for (var i = 0; i < bindings.length; ++i) { | ||
if (angular.element(bindings[i]).data().$binding[0].exp == binding) { | ||
matches.push(bindings[i]); | ||
} | ||
} | ||
} | ||
return matches[0]; // We can only return one with webdriver.findElement. | ||
return matches[0]; // We can only return one with webdriver.findElement. | ||
}), bindingDescriptor); | ||
} | ||
}; | ||
}; | ||
/** | ||
* Usage: | ||
* <select ng-model="user" ng-options="user.name for user in users"></select> | ||
* ptor.findElement(protractor.By.select("user")); | ||
*/ | ||
ProtractorBy.prototype.select = function(model) { | ||
@@ -101,3 +157,3 @@ return { | ||
using: 'css selector', | ||
value: 'select[ng-model=' + model + '] option[selected]' | ||
value: 'select[ng-model=' + model + '] option:checked' | ||
}; | ||
@@ -111,5 +167,54 @@ }; | ||
}; | ||
} | ||
ProtractorBy.prototype.repeater = null; | ||
}; | ||
exports.By = new ProtractorBy(); | ||
/** | ||
* Usage: | ||
* <div ng-repeat = "cat in pets"> | ||
* <span>{{cat.name}}</span> | ||
* <span>{{cat.age}}</span> | ||
* </div> | ||
* | ||
* // Returns the DIV for the second cat. | ||
* var secondCat = ptor.findElement( | ||
* protractor.By.repeater("cat in pets").row(2)); | ||
* // Returns the SPAN for the first cat's name. | ||
* var firstCatName = ptor.findElement( | ||
* protractor.By.repeater("cat in pets").row(1).column("{{cat.name}}")); | ||
*/ | ||
ProtractorBy.prototype.repeater = function(repeatDescriptor) { | ||
return { | ||
row: function(index) { | ||
return { | ||
using: 'css selector', | ||
value: '[ng-repeat="' + repeatDescriptor | ||
+ '"]:nth-of-type(' + index + ')', | ||
column: function(binding) { | ||
return { | ||
findOverride: function(driver) { | ||
return driver.findElement(webdriver.By.js(function() { | ||
var matches = []; | ||
var repeater = arguments[0]; | ||
var index = arguments[1]; | ||
var binding = arguments[2]; | ||
var rows = document.querySelectorAll('[ng-repeat="' | ||
+ repeater + '"]'); | ||
var row = rows[index - 1]; | ||
var bindings = row.getElementsByClassName('ng-binding'); | ||
for (var i = 0; i < bindings.length; ++i) { | ||
if (angular.element(bindings[i]).data().$binding[0].exp == binding) { | ||
matches.push(bindings[i]); | ||
} | ||
} | ||
// We can only return one with webdriver.findElement. | ||
return matches[0]; | ||
}), repeatDescriptor, index, binding); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
}; | ||
}; | ||
exports.By = new ProtractorBy(); |
@@ -32,5 +32,4 @@ Protractor | ||
Install the npm modules for selenium-webdriver and protractor: | ||
Install the npm modules for protractor, which will install selenium-webdriver if it's not already there: | ||
npm install selenium-webdriver | ||
npm install protractor | ||
@@ -53,3 +52,3 @@ | ||
To use with chrome browsers, [download chromedriver](https://code.google.com/p/chromedriver/downloads/list) | ||
To use with chrome browsers, [download chromedriver](https://code.google.com/p/chromedriver/downloads/list). | ||
[More information about chromedriver](https://code.google.com/p/selenium/wiki/ChromeDriver) | ||
@@ -56,0 +55,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
10640
219
57