protractor
Advanced tools
Comparing version 0.17.0 to 0.18.0
@@ -0,2 +1,56 @@ | ||
# 0.18.0 | ||
_Note: Major version 0 releases are for initial development, and backwards incompatible changes may be introduced at any time._ | ||
## Features | ||
- ([e3b1e7c](https://github.com/angular/protractor/commit/e3b1e7cec7af35f2e245ca64e4f94227ecaa1c57)) | ||
feat(config): add option to exclude specs based on file patterns | ||
The config now accepts `exclude`, an array of patterns to exclude. | ||
- ([88a1e58](https://github.com/angular/protractor/commit/88a1e587a40f0e6d978b20fe55160a18e2855493)) | ||
Feat(clientSideScripts): Add by.buttonText, by.partialButtonText | ||
Adds client side JS implementations of by.buttonText and by.partialButtonText, enabling element | ||
lookup based on innerText. | ||
Closes #452 | ||
- ([8d29c93](https://github.com/angular/protractor/commit/8d29c939766f044d910401e60834769cf8e5e44b)) | ||
feat(config): allow LiveScript configuration files | ||
## Bug Fixes | ||
- ([d06d931](https://github.com/angular/protractor/commit/d06d931e1cb2c2bd38c2c50965a6f78690bdc336)) | ||
fix(timeouts): fix an obscure cause of firefox timeouts | ||
Fixes #493 | ||
- ([de39e50](https://github.com/angular/protractor/commit/de39e5077d09daaeb885767e968a5cef78c9cac7)) | ||
fix(jasminewd): support multi-argument matchers | ||
Implement support for multi-argument matchers in promise wrapper. | ||
Closes #477 | ||
- ([11c4210](https://github.com/angular/protractor/commit/11c4210fe740771707d5421a4940bdce43d3d33e)) | ||
fix(testForAngular): add a message when page load does not complete in time | ||
- ([6ae6261](https://github.com/angular/protractor/commit/6ae626158ee0610b70501af5d57ad4ff379c5ead)) | ||
refactor(waitForAngular): improve error messages when timeouts occur | ||
- ([5dd93c2](https://github.com/angular/protractor/commit/5dd93c2397a401011e16271f6472c72037c871b6)) | ||
fix(config): allow CoffeeScript 1.7 to be used | ||
CoffeeScript now requires a register call to be made. | ||
- ([10aec0f](https://github.com/angular/protractor/commit/10aec0ff212987bfdb9ab4011e6cb2f9c646fca2)) | ||
fix(pageload): increase wait timeout | ||
The 300 ms wait caused problems when testing IE on Sauce Labs. It seems way too short. | ||
"browser.get()" invariably timed out. Increasing it solved our problem. | ||
# 0.17.0 | ||
_Note: Major version 0 releases are for initial development, and backwards incompatible changes may be introduced at any time._ | ||
@@ -116,3 +170,3 @@ | ||
until just before `onPrepare` to load the framework. This means that `jasmine` will | ||
not be available in global until `onPrepare`. For exampel, this means that requiring | ||
not be available in global until `onPrepare`. For example, this means that requiring | ||
the jasmine-reporters module must be done inside onPrepare, since that module expects | ||
@@ -119,0 +173,0 @@ jasmine to be available at the time it is loaded. |
@@ -150,6 +150,6 @@ Protractor API | ||
: | ||
`Protractor.By.linkText` function( ) | ||
`Protractor.By.linkText` function( ) | ||
: | ||
`Protractor.By.partialLinkText` function( ) | ||
`Protractor.By.partialLinkText` function( ) | ||
@@ -183,4 +183,9 @@ : | ||
: | ||
`Protractor.By.buttonText` function( ) | ||
: | ||
`Protractor.By.partialButtonText` function( ) | ||
WebElements | ||
@@ -187,0 +192,0 @@ ----------- |
@@ -74,5 +74,11 @@ /** | ||
function wrapMatcher(matcher, actualPromise, not) { | ||
return function(expected) { | ||
return function() { | ||
var originalArgs = arguments; | ||
actualPromise.then(function(actual) { | ||
var expected = originalArgs[0]; | ||
if (expected instanceof webdriver.promise.Promise) { | ||
if (originalArgs.length > 1) { | ||
throw error('Multi-argument matchers with promises are not ' | ||
+ 'supported.'); | ||
} | ||
expected.then(function(exp) { | ||
@@ -86,7 +92,7 @@ if (not) { | ||
} else { | ||
var expectation = expect(actual); | ||
if (not) { | ||
expect(actual).not[matcher](expected) | ||
} else { | ||
expect(actual)[matcher](expected); | ||
expectation = expectation.not; | ||
} | ||
expectation[matcher].apply(expectation, originalArgs); | ||
} | ||
@@ -93,0 +99,0 @@ }); |
@@ -45,3 +45,8 @@ require('../index.js'); | ||
}); | ||
} | ||
}, | ||
getDecimalNumber: function() { | ||
return flow.execute(function() { | ||
return webdriver.promise.fulfilled(3.14159); | ||
}); | ||
} | ||
}; | ||
@@ -115,2 +120,12 @@ }; | ||
it('should pass multiple arguments to matcher', function() { | ||
// Passing specific precision | ||
expect(fakeDriver.getDecimalNumber()).toBeCloseTo(3.1, 1); | ||
expect(fakeDriver.getDecimalNumber()).not.toBeCloseTo(3.1, 2); | ||
// Using default precision (2) | ||
expect(fakeDriver.getDecimalNumber()).not.toBeCloseTo(3.1); | ||
expect(fakeDriver.getDecimalNumber()).toBeCloseTo(3.14); | ||
}); | ||
describe('not', function() { | ||
@@ -117,0 +132,0 @@ it('should still pass normal synchronous tests', function() { |
@@ -12,10 +12,17 @@ /** | ||
try { | ||
require('coffee-script'); | ||
require('coffee-script').register(); | ||
} catch (e) { | ||
// Intentinally blank - ignore if coffee-script is not available. | ||
// Intentionally blank - ignore if coffee-script is not available. | ||
} | ||
// LiveScript is required here to enable config files written in LiveScript. | ||
// It's not directly used in this file, and not required. | ||
try { | ||
require('LiveScript'); | ||
} catch (e) { | ||
// Intentionally blank - ignore if LiveScript is not available. | ||
} | ||
var util = require('util'); | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var runner = require('./runner.js'); | ||
@@ -35,2 +42,3 @@ var argv = require('optimist'). | ||
describe('specs', 'Comma-separated list of files to test'). | ||
describe('exclude', 'Comma-separated list of files to exclude'). | ||
describe('verbose', 'Print full spec names'). | ||
@@ -60,14 +68,19 @@ describe('stackTrace', 'Print stack trace on error'). | ||
if (argv.version) { | ||
util.puts('Version ' + JSON.parse( | ||
fs.readFileSync(__dirname + '/../package.json', 'utf8')).version); | ||
util.puts('Version ' + require(path.join(__dirname, '../package.json')).version); | ||
process.exit(0); | ||
} | ||
// Any file names should be resolved relative to the current working directory. | ||
if (argv.specs) { | ||
argv.specs = argv.specs.split(','); | ||
argv.specs.forEach(function(spec, index, arr) { | ||
arr[index] = path.resolve(process.cwd(), spec); | ||
}); | ||
var processFilePatterns = function(patterns) { | ||
if (patterns) { | ||
patterns = patterns.split(','); | ||
patterns.forEach(function(spec, index, arr) { | ||
arr[index] = path.resolve(process.cwd(), spec); | ||
}); | ||
} | ||
} | ||
processFilePatterns(argv.specs); | ||
processFilePatterns(argv.exclude); | ||
['seleniumServerJar', 'chromeDriver', 'onPrepare'].forEach(function(name) { | ||
@@ -74,0 +87,0 @@ if (argv[name]) { |
@@ -36,3 +36,3 @@ /** | ||
* | ||
* @return {Array.<WebElement>} The elements containing the binding. | ||
* @return {Array.<Element>} The elements containing the binding. | ||
*/ | ||
@@ -346,3 +346,3 @@ clientSideScripts.findBindings = function() { | ||
/** | ||
* Find a elements by model name. | ||
* Find elements by model name. | ||
* | ||
@@ -368,2 +368,61 @@ * arguments[0] {Element} The scope of the search. | ||
/** | ||
* Find buttons by textual content. | ||
* | ||
* arguments[0] {Element} The scope of the search. | ||
* arguments[1] {string} The exact text to match. | ||
* | ||
* @return {Array.<Element>} The matching elements. | ||
*/ | ||
clientSideScripts.findByButtonText = function() { | ||
var using = arguments[0] || document; | ||
var searchText = arguments[1]; | ||
var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]'); | ||
var matches = []; | ||
for (var i = 0; i < elements.length; ++i) { | ||
var element = elements[i]; | ||
var elementText; | ||
if (element.tagName.toLowerCase() == "button") { | ||
elementText = element.innerText || element.textContent; | ||
} else { | ||
elementText = element.value; | ||
} | ||
if (elementText === searchText) { | ||
matches.push(element); | ||
} | ||
} | ||
return matches; | ||
}; | ||
/** | ||
* Find buttons by textual content. | ||
* | ||
* arguments[0] {Element} The scope of the search. | ||
* arguments[1] {string} The exact text to match. | ||
* | ||
* @return {Array.<Element>} The matching elements. | ||
*/ | ||
clientSideScripts.findByPartialButtonText = function() { | ||
var using = arguments[0] || document; | ||
var searchText = arguments[1]; | ||
var elements = using.querySelectorAll('button, input[type="button"], input[type="submit"]'); | ||
var matches = []; | ||
for (var i = 0; i < elements.length; ++i) { | ||
var element = elements[i]; | ||
var elementText; | ||
if (element.tagName.toLowerCase() == "button") { | ||
elementText = element.innerText || element.textContent; | ||
} else { | ||
elementText = element.value; | ||
} | ||
if (elementText.indexOf(searchText) > -1) { | ||
matches.push(element); | ||
} | ||
} | ||
return matches; | ||
}; | ||
/** | ||
* Find multiple select elements by model name. | ||
@@ -442,3 +501,8 @@ * | ||
var attempts = arguments[0]; | ||
var callback = arguments[arguments.length - 1]; | ||
var asyncCallback = arguments[arguments.length - 1]; | ||
var callback = function(args) { | ||
setTimeout(function() { | ||
asyncCallback(args); | ||
}, 0); | ||
}; | ||
var check = function(n) { | ||
@@ -445,0 +509,0 @@ try { |
@@ -124,2 +124,33 @@ var util = require('util'); | ||
/** | ||
* Usage: | ||
* <button>Save</button> | ||
* element(by.buttonText("Save")); | ||
*/ | ||
ProtractorBy.prototype.buttonText = function(searchText) { | ||
return { | ||
findElementsOverride: function(driver, using) { | ||
return driver.findElements( | ||
webdriver.By.js(clientSideScripts.findByButtonText), using, searchText); | ||
}, | ||
message: 'by.buttonText("' + searchText + '")' | ||
}; | ||
}; | ||
/** | ||
* Usage: | ||
* <button>Save my file</button> | ||
* element(by.partialButtonText("Save")); | ||
*/ | ||
ProtractorBy.prototype.partialButtonText = function(searchText) { | ||
return { | ||
findElementsOverride: function(driver, using) { | ||
return driver.findElements( | ||
webdriver.By.js(clientSideScripts.findByPartialButtonText), using, searchText); | ||
}, | ||
message: 'by.partialButtonText("' + searchText + '")' | ||
}; | ||
}; | ||
/** | ||
* @DEPRECATED - use 'model' instead. | ||
@@ -126,0 +157,0 @@ * Usage: |
@@ -414,8 +414,20 @@ var url = require('url'); | ||
}).then(null, function(err) { | ||
if (!/asynchronous script timeout/.test(err.message)) { | ||
var timeout; | ||
if (/asynchronous script timeout/.test(err.message)) { | ||
// Timeout on Chrome | ||
timeout = /[\d\.]*\ seconds/.exec(err.message); | ||
} else if (/Timed out waiting for async script/.test(err.message)) { | ||
// Timeout on Firefox | ||
timeout = /[\d\.]*ms/.exec(err.message); | ||
} else if (/Timed out waiting for an asynchronous script/.test(err.message)) { | ||
// Timeout on Safari | ||
timeout = /[\d\.]*\ ms/.exec(err.message); | ||
} | ||
if (timeout) { | ||
throw 'Timed out waiting for Protractor to synchronize with ' + | ||
'the page after ' + timeout + '. Please see ' + | ||
'https://github.com/angular/protractor/blob/master/docs/faq.md'; | ||
} else { | ||
throw err; | ||
} | ||
var timeout = /[\d\.]*\ seconds/.exec(err.message); | ||
throw 'Timed out waiting for Protractor to synchronize with ' + | ||
'the page after ' + timeout; | ||
}); | ||
@@ -663,3 +675,3 @@ }; | ||
}); | ||
}, 300); | ||
}, timeout * 1000, 'Timed out waiting for page to load'); | ||
@@ -666,0 +678,0 @@ var assertAngularOnPage = function(arr) { |
@@ -218,3 +218,29 @@ 'use strict'; | ||
/** | ||
* Resolve a list of file patterns into a list of individual file paths. | ||
* | ||
* @param {array} patterns | ||
* @param {boolean} opt_omitWarnings whether to omit did not match warnings | ||
* | ||
* @return {array} The resolved file paths. | ||
*/ | ||
var resolveFilePatterns = function(patterns, opt_omitWarnings) { | ||
var resolvedFiles = []; | ||
if (patterns) { | ||
for (var i = 0; i < patterns.length; ++i) { | ||
var matches = glob.sync(patterns[i], {cwd: config.configDir}); | ||
if (!matches.length && !opt_omitWarnings) { | ||
util.puts('Warning: pattern ' + patterns[i] + ' did not match any files.'); | ||
} | ||
for (var j = 0; j < matches.length; ++j) { | ||
resolvedFiles.push(path.resolve(config.configDir, matches[j])); | ||
} | ||
} | ||
} | ||
return resolvedFiles; | ||
}; | ||
/** | ||
* Set up webdriver and run the tests. Note that due to the current setup of | ||
@@ -231,13 +257,8 @@ * loading Jasmine and the test specs, this should only be run once. | ||
} | ||
var specs = config.specs; | ||
var resolvedSpecs = []; | ||
for (var i = 0; i < specs.length; ++i) { | ||
var matches = glob.sync(specs[i], {cwd: config.configDir}); | ||
if (!matches.length) { | ||
util.puts('Warning: pattern ' + specs[i] + ' did not match any files.'); | ||
} | ||
for (var j = 0; j < matches.length; ++j) { | ||
resolvedSpecs.push(path.resolve(config.configDir, matches[j])); | ||
} | ||
} | ||
var resolvedExcludes = resolveFilePatterns(config.exclude, true); | ||
var resolvedSpecs = resolveFilePatterns(config.specs).filter(function (path) { | ||
return resolvedExcludes.indexOf(path) < 0; | ||
}); | ||
if (!resolvedSpecs.length) { | ||
@@ -244,0 +265,0 @@ throw new Error('Spec patterns did not match any files.'); |
@@ -44,3 +44,3 @@ { | ||
"license" : "MIT", | ||
"version": "0.17.0", | ||
"version": "0.18.0", | ||
"webdriverVersions": { | ||
@@ -47,0 +47,0 @@ "selenium": "2.39.0", |
@@ -59,2 +59,5 @@ // A reference configuration file. | ||
// Patterns to exclude. | ||
exclude: [], | ||
// ----- Capabilities to be passed to the webdriver instance ---- | ||
@@ -61,0 +64,0 @@ // |
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
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
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
185855
2713