protractor
Advanced tools
Comparing version 0.12.0 to 0.12.1
@@ -0,1 +1,53 @@ | ||
# 0.12.1 | ||
_Note: Major version 0 releases are for initial development, and backwards compatible changes may be introduced at any time._ | ||
## Minor features | ||
- ([201b59c](https://github.com/angular/protractor/commit/201b59c2e728c56d2a88a1167ed3007b22ab9034)) feat(jasminewd): better error messaging when expect is called with a WebElement | ||
- ([d383770](https://github.com/angular/protractor/commit/d383770499da4b08b74ad53c20ffa288147f94e9)) feat(clientsidescripts): better error reporting from testForAngular and waitForAngular | ||
## Bug fixes | ||
- ([8580c0c](https://github.com/angular/protractor/commit/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a)) fix(install-selenium): update to chromedriver 2.6 | ||
Update to the latest version of Chromedriver. This fixes the issue with | ||
OS X 10.9. Closes #181. | ||
- ([ebc528f](https://github.com/angular/protractor/commit/ebc528fec2c2e88b0f9e32cee0661ecd79da2252)) fix(debugging): switch debugging tests to the new test app urls. | ||
- ([8ff4787](https://github.com/angular/protractor/commit/8ff47875488647513f4199bab36e3b0023dd305d)) fix(runner): exit with proper code when tests fail | ||
When errors with messages matching /timeout/ were created, Protractor | ||
clears the control flow so that the remainder of the tasks scheduled | ||
for that spec don't bleed over into the next spec. This was messing up | ||
the promises used in the runner, since they are also webdriver promises. | ||
Long term, the runner should _not_ use webdriver promises. For now, fix by | ||
having the runner resolve promises directly rather than through chaining, | ||
and add a TODO to use promises which aren't connected to WebDriver's | ||
control flow in the runner. | ||
Closes #214. | ||
- ([81501c5](https://github.com/angular/protractor/commit/81501c5d941cd7edb15439cef7c7a64c0e773e27)) fix(clientsidescripts): workaround for IE 8 "async page reload" init problem | ||
- ([21264fd](https://github.com/angular/protractor/commit/21264fdc2f6cb3345c8f005936c74985ecd811dc)) fix(find): fix error when exposed to ng-options element with a default option | ||
Protractor will now ignore elements with the ng-bind class that don't have | ||
a proper binding on their data, instead of blowing up when encoutering them. | ||
Closes #165, may fix #170 | ||
- ([f672648](https://github.com/angular/protractor/commit/f6726482cd2ce9a7dda9ccdeeb93574d3b9293e3)) fix(findelements): fix isPresent for repeaters by row for real | ||
## Breaking Changes | ||
- ([bf5b076](https://github.com/angular/protractor/commit/bf5b076cb8897d844c25baa91c263a12c61e3ab3)) fix(cli): remove boolean verbose and stack trace options | ||
Also add better description for what the command line options are. | ||
Tiny breaking change: | ||
Rename the 'includeStackTrace' command line option to 'stackTrace' for brevity. | ||
# 0.12.0 | ||
@@ -2,0 +54,0 @@ |
@@ -15,3 +15,3 @@ Protractor API | ||
Documentation generated at 6bc3ecb30d45947e9de897896a4f7378453bd6cf | ||
Documentation generated at 8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a | ||
@@ -69,3 +69,3 @@ [WebDriver](https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js) and [Protractor](https://github.com/angular/protractor/blob/master/lib/protractor.js) | ||
[**WD**](https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#609) [**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L362) : | ||
[**WD**](https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#609) [**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L463) : | ||
`get` function( _string_ ) -> _!webdriver.promise.Promise_ | ||
@@ -103,15 +103,15 @@ | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L105) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L235) : | ||
`waitForAngular` function( ) -> _!webdriver.promise.Promise_ | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L129) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L259) : | ||
`wrapWebElement` function( _webdriver.WebElement_ ) | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L340) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L441) : | ||
`addMockModule` function( _!string_ _!string|Function_ ) | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L354) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L455) : | ||
`clearMockModules` function( ) | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L397) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L498) : | ||
`debugger` function( ) | ||
@@ -143,18 +143,33 @@ | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/locators.js#L21) : | ||
: | ||
`Protractor.By.className` function( ) | ||
: | ||
`Protractor.By.linkText` function( ) | ||
: | ||
`Protractor.By.partialLinkText` function( ) | ||
: | ||
`Protractor.By.js` function( ) | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/locators.js#L21) : | ||
`Protractor.By.binding` function( ) | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/locators.js#L43) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/locators.js#L43) : | ||
`Protractor.By.select` function( ) | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/locators.js#L61) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/locators.js#L61) : | ||
`Protractor.By.selectedOption` function( ) | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/locators.js#L78) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/locators.js#L79) : | ||
`Protractor.By.input` function( ) | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/locators.js#L96) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/locators.js#L98) : | ||
`Protractor.By.model` function( ) | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/locators.js#L116) : | ||
`Protractor.By.textarea` function( ) | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/locators.js#L110) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/locators.js#L130) : | ||
`Protractor.By.repeater` function( ) | ||
@@ -179,9 +194,9 @@ | ||
[**WD**](https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#1591) [**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L268) : | ||
[**WD**](https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#1591) [**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L382) : | ||
`WebElement.findElement` function( _webdriver.Locator|Object.<string>_ _..._ ) -> _webdriver.WebElement_ | ||
[**WD**](https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#1634) [**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L324) : | ||
[**WD**](https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#1634) [**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L425) : | ||
`WebElement.isElementPresent` function( _webdriver.Locator|Object.<string>_ _..._ ) -> _!webdriver.promise.Promise_ | ||
[**WD**](https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#1659) [**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L299) : | ||
[**WD**](https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#1659) [**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L400) : | ||
`WebElement.findElements` function( _webdriver.Locator|Object.<string>_ _..._ ) -> _!webdriver.promise.Promise_ | ||
@@ -234,9 +249,12 @@ | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L256) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L87) : | ||
`WebElement.all` function( ) | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L281) : | ||
`WebElement.$` function( _string_ ) -> _!webdriver.WebElement_ | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L286) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L310) : | ||
`WebElement.$$` function( _string_ ) -> _!webdriver.promise.Promise_ | ||
[**P**](https://github.com/angular/protractor/blob/6bc3ecb30d45947e9de897896a4f7378453bd6cf/lib/protractor.js#L237) : | ||
[**P**](https://github.com/angular/protractor/blob/8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a/lib/protractor.js#L363) : | ||
`WebElement.evaluate` function( _string_ ) -> _!webdriver.promise.Promise_ | ||
@@ -243,0 +261,0 @@ |
@@ -32,3 +32,3 @@ FAQ | ||
Karma is a great tool for unit testing, and Protractor is intended for | ||
end to end or intergration testing. This means that small tests for the logic | ||
end to end or integration testing. This means that small tests for the logic | ||
of your individual controllers, directives, and services should be run using | ||
@@ -63,1 +63,17 @@ Karma. Big tests in which you have a running instance of your entire application | ||
empty `getText` values. Instead, try `element.getAttribute('value')`. | ||
How can I interact directly with the JavaScript running in my app? | ||
------------------------------------------------------------------ | ||
In general, the design of WebDriver tests is to interact with the page as a user would, so it gets a little tricky if you want to interact with the JavaScript directly. You should avoid it unless you have a good reason. However, there are ways of doing it. | ||
You can use the evaluate function on a WebElement to get the value of an Angular expression in the scope of that element. e.g. | ||
```javascript | ||
by.css('.foo').evaluate('bar') | ||
``` | ||
would return whatever `{{bar}}` is in the scope of the element with class 'foo'. | ||
You can also execute arbitrary JavaScript in the browser with | ||
```javascript | ||
browser.executeScript('your script as a string') | ||
``` |
@@ -9,3 +9,3 @@ var fs = require('fs'); | ||
var versionHash ='6bc3ecb30d45947e9de897896a4f7378453bd6cf'; | ||
var versionHash ='8580c0c76c5ccd3c55d053e59d8df37b3c4cf35a'; | ||
@@ -106,2 +106,6 @@ var NEW_LINE = /\n\r?/; | ||
}, { name: 'tagName' | ||
}, { name: 'className' | ||
}, { name: 'linkText' | ||
}, { name: 'partialLinkText' | ||
}, { name: 'js' | ||
} | ||
@@ -108,0 +112,0 @@ ]; |
@@ -35,5 +35,5 @@ Getting Started | ||
(or omit the -g if you'd prefer not to install globally). | ||
(or omit the -g if you'd prefer not to install globally). | ||
The example test expects a selenium standalone server to be running at | ||
The example test expects a selenium standalone server to be running at | ||
localhost:4444. Protractor comes with a script to help download and install | ||
@@ -50,5 +50,5 @@ the standalone server. Run | ||
Protractor is now available as a command line program which takes one argument, | ||
a configuration file. | ||
a configuration file. | ||
protractor node_modules/protractor/example/protractorConf.js | ||
protractor node_modules/protractor/example/conf.js | ||
@@ -146,3 +146,3 @@ The configuration file tells Protractor what tests to run, how to connect to a | ||
`element` returns an ElementFinder. This is an object which allows you to interact with the element on your page, but since all interaction with the browser must be done over webdriver, it is important to remember that this is *not* a DOM element. You can interact with it with methods such as | ||
`sendKeys`, `getText`, and `click`. Check out the [API](/api.md) for a list of | ||
`sendKeys`, `getText`, and `click`. Check out the [API](/docs/api.md) for a list of | ||
all available methods. | ||
@@ -149,0 +149,0 @@ |
@@ -107,2 +107,6 @@ /** | ||
if (actual instanceof webdriver.promise.Promise) { | ||
if (actual instanceof webdriver.WebElement) { | ||
throw 'expect called with WebElement argment, expected a Promise. ' + | ||
'Did you mean to use .getText()?'; | ||
} | ||
return promiseMatchers(actual); | ||
@@ -109,0 +113,0 @@ } else { |
@@ -13,2 +13,5 @@ require('../index.js'); | ||
return { | ||
controlFlow: function() { | ||
return flow; | ||
}, | ||
sleep: function(ms) { | ||
@@ -112,3 +115,11 @@ return flow.timeout(ms); | ||
it('should throw an error with a WebElement actual value', function() { | ||
var webElement = new webdriver.WebElement(fakeDriver, 'idstring'); | ||
expect(function() { | ||
expect(webElement).toEqual(4); | ||
}).toThrow('expect called with WebElement argment, expected a Promise. ' + | ||
'Did you mean to use .getText()?'); | ||
}); | ||
// Uncomment to see timeout failures. | ||
@@ -115,0 +126,0 @@ // it('should timeout after 200ms', function() { |
/** | ||
* The command line interface for interacting with the Protractor runner. | ||
* It takes care of parsing the config file and command line options. | ||
* | ||
* Values from command line options override values from the config. | ||
*/ | ||
@@ -11,3 +13,5 @@ | ||
var argv = require('optimist'). | ||
usage('Usage: protractor [options] [config]'). | ||
usage('Usage: protractor [options] [configFile]\n' + | ||
'The [options] object will override values from the config file.\n' + | ||
'See the reference config for a full list of options.'). | ||
describe('version', 'Print Protractor version'). | ||
@@ -22,3 +26,3 @@ describe('browser', 'Browsername, e.g. chrome or firefox'). | ||
describe('verbose', 'Print full spec names'). | ||
describe('includeStackTrace', 'Print stack trace on error'). | ||
describe('stackTrace', 'Print stack trace on error'). | ||
describe('params', 'Param object to be passed to the tests'). | ||
@@ -31,6 +35,4 @@ alias('browser', 'capabilities.browserName'). | ||
alias('build', 'capabilities.build'). | ||
boolean('verbose'). | ||
boolean('includeStackTrace'). | ||
alias('verbose', 'jasmineNodeOpts.isVerbose'). | ||
alias('includeStackTrace', 'jasmineNodeOpts.includeStackTrace'). | ||
alias('stackTrace', 'jasmineNodeOpts.includeStackTrace'). | ||
check(function(arg) { | ||
@@ -37,0 +39,0 @@ if (arg._.length > 1) { |
@@ -15,2 +15,3 @@ /** | ||
* | ||
* Asynchronous. | ||
* arguments[0] {string} The selector housing an ng-app | ||
@@ -22,4 +23,8 @@ * arguments[1] {function} callback | ||
var callback = arguments[1]; | ||
angular.element(el).injector().get('$browser'). | ||
notifyWhenNoOutstandingRequests(callback); | ||
try { | ||
angular.element(el).injector().get('$browser'). | ||
notifyWhenNoOutstandingRequests(callback); | ||
} catch (e) { | ||
callback(e); | ||
} | ||
}; | ||
@@ -41,4 +46,7 @@ | ||
for (var i = 0; i < bindings.length; ++i) { | ||
var bindingName = angular.element(bindings[i]).data().$binding[0].exp || | ||
angular.element(bindings[i]).data().$binding; | ||
var elemData = angular.element(bindings[i]).data(); | ||
if (!elemData || !elemData.$binding) { | ||
continue; | ||
} | ||
var bindingName = elemData.$binding[0].exp || elemData.$binding; | ||
if (bindingName.indexOf(binding) != -1) { | ||
@@ -65,4 +73,7 @@ matches.push(bindings[i]); | ||
for (var i = 0; i < bindings.length; ++i) { | ||
var bindingName = angular.element(bindings[i]).data().$binding[0].exp || | ||
angular.element(bindings[i]).data().$binding; | ||
var elemData = angular.element(bindings[i]).data(); | ||
if (!elemData || !elemData.$binding) { | ||
continue; | ||
} | ||
var bindingName = elemData.$binding[0].exp || elemData.$binding; | ||
if (bindingName.indexOf(binding) != -1) { | ||
@@ -105,2 +116,33 @@ matches.push(bindings[i]); | ||
/** | ||
* Find an array of elements matching a row within an ng-repeat. There | ||
* will only be one element, but this is necessary for isElementPresent. | ||
* | ||
* arguments[0] {Element} The scope of the search. | ||
* arguments[1] {string} The text of the repeater, e.g. 'cat in cats'. | ||
* arguments[2] {number} The row index. | ||
* | ||
* @return {Array.<Element>} An array of a single element, the row of the | ||
* repeater. | ||
*/ | ||
clientSideScripts.findRepeaterRows = function() { | ||
var using = arguments[0] || document; | ||
var repeater = arguments[1]; | ||
var index = arguments[2]; | ||
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 = using.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]]; | ||
}; | ||
/** | ||
* Find all rows of an ng-repeat. | ||
@@ -171,4 +213,7 @@ * | ||
for (var i = 0; i < bindings.length; ++i) { | ||
var bindingName = angular.element(bindings[i]).data().$binding[0].exp || | ||
angular.element(bindings[i]).data().$binding; | ||
var elemData = angular.element(bindings[i]).data(); | ||
if (!elemData || !elemData.$binding) { | ||
continue; | ||
} | ||
var bindingName = elemData.$binding[0].exp || elemData.$binding; | ||
if (bindingName.indexOf(binding) != -1) { | ||
@@ -219,4 +264,7 @@ matches.push(bindings[i]); | ||
for (var j = 0; j < bindings.length; ++j) { | ||
var bindingName = angular.element(bindings[j]).data().$binding[0].exp || | ||
angular.element(bindings[j]).data().$binding; | ||
var elemData = angular.element(bindings[j]).data(); | ||
if (!elemData || !elemData.$binding) { | ||
continue; | ||
} | ||
var bindingName = elemData.$binding[0].exp || elemData.$binding; | ||
if (bindingName.indexOf(binding) != -1) { | ||
@@ -231,3 +279,3 @@ matches.push(bindings[j]); | ||
/** | ||
* Find an input element by model name. | ||
* Find input element by model name. | ||
* | ||
@@ -237,5 +285,5 @@ * arguments[0] {Element} The scope of the search. | ||
* | ||
* @return {Array.<Element?} The matching input elements. | ||
* @return {Element} The first matching input element. | ||
*/ | ||
clientSideScripts.findInputs = function() { | ||
clientSideScripts.findInput = function() { | ||
var using = arguments[0] || document; | ||
@@ -248,3 +296,3 @@ var model = arguments[1]; | ||
if (inputs.length) { | ||
return inputs; | ||
return inputs[0]; | ||
} | ||
@@ -255,3 +303,3 @@ } | ||
/** | ||
* Find input elements by model name. | ||
* Find an input elements by model name. | ||
* | ||
@@ -261,5 +309,5 @@ * arguments[0] {Element} The scope of the search. | ||
* | ||
* @return {Element} The first matching input element. | ||
* @return {Array.<Element>} The matching input elements. | ||
*/ | ||
clientSideScripts.findInput = function() { | ||
clientSideScripts.findInputs = function() { | ||
var using = arguments[0] || document; | ||
@@ -272,3 +320,3 @@ var model = arguments[1]; | ||
if (inputs.length) { | ||
return inputs[0]; | ||
return inputs; | ||
} | ||
@@ -388,3 +436,5 @@ } | ||
* | ||
* arguments none. | ||
* Asynchronous. | ||
* arguments[0] {number} Number of times to retry. | ||
* arguments[1] {function} callback | ||
*/ | ||
@@ -395,8 +445,16 @@ clientSideScripts.testForAngular = function() { | ||
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); | ||
try { | ||
if (window.angular && window.angular.resumeBootstrap) { | ||
callback([true, null]); | ||
} else if (n < 1) { | ||
if (window.angular) { | ||
callback([false, 'angular never provided resumeBootstrap']); | ||
} else { | ||
callback([false, 'retries looking for angular exceeded']); | ||
} | ||
} else { | ||
window.setTimeout(function() {check(n - 1)}, 1000); | ||
} | ||
} catch (e) { | ||
callback([false, e]); | ||
} | ||
@@ -403,0 +461,0 @@ }; |
@@ -164,2 +164,7 @@ var util = require('util'); | ||
}, | ||
findArrayOverride: function(driver, using) { | ||
return driver.findElements( | ||
webdriver.By.js(clientSideScripts.findRepeaterRows), | ||
using, repeatDescriptor, index); | ||
}, | ||
column: function(binding) { | ||
@@ -166,0 +171,0 @@ return { |
@@ -248,10 +248,15 @@ var url = require('url'); | ||
return this.driver.executeAsyncScript( | ||
clientSideScripts.waitForAngular, this.rootEl).then(null, function(err) { | ||
if (!/asynchronous script timeout/.test(err.message)) { | ||
throw err; | ||
} | ||
var timeout = /[\d\.]*\ seconds/.exec(err.message); | ||
throw 'Timed out waiting for Protractor to synchronize with ' + | ||
'the page after ' + timeout; | ||
}); | ||
clientSideScripts.waitForAngular, this.rootEl).then(function(browserErr) { | ||
if (browserErr) { | ||
throw 'Error while waiting for Protractor to ' + | ||
'sync with the page: ' + JSON.stringify(browserErr); | ||
} | ||
}).then(null, function(err) { | ||
if (!/asynchronous script timeout/.test(err.message)) { | ||
throw err; | ||
} | ||
var timeout = /[\d\.]*\ seconds/.exec(err.message); | ||
throw 'Timed out waiting for Protractor to synchronize with ' + | ||
'the page after ' + timeout; | ||
}); | ||
}; | ||
@@ -469,5 +474,11 @@ | ||
* Navigate to the given destination and loads mock modules before | ||
* Angular. | ||
* Angular. Assumes that the page being loaded uses Angular. | ||
* If you need to access a page which does have Angular on load, use | ||
* the wrapped webdriver directly. | ||
* | ||
* @param {string} destination Destination URL. | ||
* @param {=number} opt_timeout Number of seconds to wait for Angular to start. | ||
*/ | ||
Protractor.prototype.get = function(destination) { | ||
Protractor.prototype.get = function(destination, opt_timeout) { | ||
var timeout = opt_timeout || 10; | ||
destination = url.resolve(this.baseUrl, destination); | ||
@@ -480,8 +491,29 @@ | ||
var assertAngularOnPage = function(arr) { | ||
var hasAngular = arr[0]; | ||
if (!hasAngular) { | ||
var message = arr[1]; | ||
throw new Error('Angular could not be found on the page ' + | ||
destination + " : " + message); | ||
} | ||
}; | ||
// Make sure the page is an Angular page. | ||
this.driver.executeAsyncScript(clientSideScripts.testForAngular, 10). | ||
then(function(hasAngular) { | ||
if (!hasAngular) { | ||
throw new Error('Angular could not be found on the page ' + | ||
destination); | ||
var self = this; | ||
self.driver.executeAsyncScript(clientSideScripts.testForAngular, timeout). | ||
then(assertAngularOnPage, function(err) { | ||
if (/reload detected during async script/.test(err.message)) { | ||
// Sometimes IE will fail to run scripts right after a location change. | ||
// Let's try it once more. | ||
self.driver.executeAsyncScript( | ||
clientSideScripts.testForAngular, timeout). | ||
then(assertAngularOnPage, function(err) { | ||
if (/reload detected during async script/.test(err.message)) { | ||
throw 'Persistent async reload interrupt problem: ' + err.message; | ||
} else { | ||
throw 'Error while running testForAngular: ' + err.message; | ||
} | ||
}); | ||
} else { | ||
throw 'Error while running testForAngular: ' + err.message; | ||
} | ||
@@ -493,3 +525,8 @@ }); | ||
for (var i = 0; i < this.moduleScripts_.length; ++i) { | ||
this.driver.executeScript(this.moduleScripts_[i]); | ||
name = this.moduleNames_[i]; | ||
this.driver.executeScript(this.moduleScripts_[i]). | ||
then(null, function(err) { | ||
throw 'Error wile running module script ' + name + | ||
': ' + err.message; | ||
}); | ||
} | ||
@@ -496,0 +533,0 @@ |
@@ -102,3 +102,5 @@ var util = require('util'); | ||
var setUpSelenium = function() { | ||
var promise = webdriver.promise.defer(); | ||
// TODO: This should not be tied to the webdriver promise loop, it should use | ||
// another promise system instead. | ||
var deferred = webdriver.promise.defer(); | ||
@@ -114,3 +116,3 @@ if (config.sauceUser && config.sauceKey) { | ||
util.puts('Using the selenium server at ' + config.seleniumAddress); | ||
promise.fulfill(config.seleniumAddress); | ||
deferred.fulfill(config.seleniumAddress); | ||
} else if (sauceAccount) { | ||
@@ -126,3 +128,3 @@ config.capabilities.username = config.sauceUser; | ||
util.puts('Using SauceLabs selenium server at ' + config.seleniumAddress); | ||
promise.fulfill(config.seleniumAddress); | ||
deferred.fulfill(config.seleniumAddress); | ||
} else if (config.seleniumServerJar) { | ||
@@ -149,3 +151,3 @@ util.puts('Starting selenium standalone server...'); | ||
config.seleniumAddress = server.address(); | ||
promise.fulfill(config.seleniumAddress); | ||
deferred.fulfill(config.seleniumAddress); | ||
}); | ||
@@ -157,3 +159,3 @@ } else { | ||
return promise; | ||
return deferred.promise; | ||
} | ||
@@ -189,3 +191,5 @@ | ||
minijn.addSpecs(resolvedSpecs); | ||
var runPromise = webdriver.promise.defer(); | ||
// TODO: This should not be tied to the webdriver promise loop, it should use | ||
// another promise system instead. | ||
var runDeferred = webdriver.promise.defer(); | ||
driver = new webdriver.Builder(). | ||
@@ -236,3 +240,3 @@ usingServer(config.seleniumAddress). | ||
driver.quit().then(function() { | ||
runPromise.fulfill(runner); | ||
runDeferred.fulfill(runner); | ||
}); | ||
@@ -245,3 +249,3 @@ }; | ||
return runPromise; | ||
return runDeferred.promise; | ||
}; | ||
@@ -254,5 +258,9 @@ | ||
var runOnce = function() { | ||
setUpSelenium(). | ||
then(runJasmineTests). | ||
then(cleanUp); | ||
setUpSelenium().then(function() { | ||
// cleanUp must be registered directly onto runJasmineTests, not onto | ||
// the chained promise, so that cleanUp is still called in case of a | ||
// timeout error. Timeout errors need to clear the control flow, which | ||
// would mess up chaining promises. | ||
runJasmineTests().then(cleanUp); | ||
}); | ||
}; | ||
@@ -259,0 +267,0 @@ |
@@ -15,3 +15,3 @@ { | ||
"dependencies": { | ||
"selenium-webdriver": "~2.35.0", | ||
"selenium-webdriver": "~2.37.0", | ||
"minijasminenode": "~0.2.4", | ||
@@ -40,3 +40,3 @@ "saucelabs": "~0.1.0", | ||
"license" : "MIT", | ||
"version": "0.12.0" | ||
"version": "0.12.1" | ||
} |
@@ -100,4 +100,4 @@ Protractor | ||
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) | ||
To use with chrome browsers, [download chromedriver](http://chromedriver.storage.googleapis.com/index.html). | ||
[More information about chromedriver](https://sites.google.com/a/chromium.org/chromedriver/) | ||
@@ -104,0 +104,0 @@ A script is included to do the download for you - run (add the --nocd option if you do not want to install ChromeDriver) |
@@ -14,3 +14,3 @@ // A reference configuration file. | ||
// The location of the selenium standalone server .jar file. | ||
seleniumServerJar: './selenium/selenium-server-standalone-2.35.0.jar', | ||
seleniumServerJar: './selenium/selenium-server-standalone-2.37.0.jar', | ||
// The port to start the selenium server on, or null if the server should | ||
@@ -91,3 +91,3 @@ // find its own unused port. | ||
} | ||
} | ||
}, | ||
@@ -94,0 +94,0 @@ // ----- Options to be passed to minijasminenode ----- |
Sorry, the diff of this file is not supported yet
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
137399
2190
+ Addedselenium-webdriver@2.37.0(transitive)
- Removedselenium-webdriver@2.35.2(transitive)
Updatedselenium-webdriver@~2.37.0