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

Commit

Permalink
fix(find): fix error when exposed to ng-options element with a defaul…
Browse files Browse the repository at this point in the history
…t 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
  • Loading branch information
juliemr committed Nov 8, 2013
1 parent fb46ec9 commit 21264fd
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 16 deletions.
44 changes: 28 additions & 16 deletions lib/clientsidescripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ clientSideScripts.findBinding = function() {
var bindings = using.getElementsByClassName('ng-binding');
var matches = [];
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) {
matches.push(bindings[i]);
}
Expand All @@ -64,8 +67,11 @@ clientSideScripts.findBindings = function() {
var bindings = using.getElementsByClassName('ng-binding');
var matches = [];
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) {
matches.push(bindings[i]);
}
Expand Down Expand Up @@ -168,8 +174,11 @@ clientSideScripts.findRepeaterElement = function() {
bindings.push(childBindings[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) {
matches.push(bindings[i]);
}
Expand Down Expand Up @@ -215,8 +224,11 @@ clientSideScripts.findRepeaterColumn = function() {
bindings.push(childBindings[k]);
}
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) {
matches.push(bindings[j]);
}
Expand All @@ -226,43 +238,43 @@ clientSideScripts.findRepeaterColumn = function() {
};

/**
* Find an input element by model name.
* Find input element by model name.
*
* arguments[0] {Element} The scope of the search.
* arguments[1] {string} The model name.
*
* @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;
var model = arguments[1];
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 = using.querySelectorAll(selector);
if (inputs.length) {
return inputs;
return inputs[0];
}
}
};

/**
* Find input elements by model name.
* Find an input elements by model name.
*
* arguments[0] {Element} The scope of the search.
* arguments[1] {string} The model name.
*
* @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;
var model = arguments[1];
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 = using.querySelectorAll(selector);
if (inputs.length) {
return inputs[0];
return inputs;
}
}
};
Expand Down
5 changes: 5 additions & 0 deletions lib/locators.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ ProtractorBy.prototype.repeater = function(repeatDescriptor) {
webdriver.By.js(clientSideScripts.findRepeaterRow),
using, repeatDescriptor, index);
},
findArrayOverride: function(driver, using) {
return driver.findElement(
webdriver.By.js(clientSideScripts.findAllRepeaterRows),

This comment has been minimized.

Copy link
@MexicanAce

MexicanAce Nov 8, 2013

Using findAllRepeaterRows will give false positives for isElementPresent if the row index provided is larger than the length of the returned array.

Example: ptor.isElementPresent(protractor.By.repeater('user in users').row('100')) is true even if the returned array is only length 2

This comment has been minimized.

Copy link
@juliemr

juliemr Nov 12, 2013

Author Member

Of course you're right. Fixing...

using, repeatDescriptor);
},
column: function(binding) {
return {
findOverride: function(driver, using) {
Expand Down
13 changes: 13 additions & 0 deletions spec/basic/findelements_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,24 @@ describe('locators', function() {
expect(arr.length).toEqual(3);
});
});
});

describe('by select', function() {
it('should find multiple selects', function() {
browser.findElements(by.select('dayColor.color')).then(function(arr) {
expect(arr.length).toEqual(3);
});
});

it('should find the select and concat its options', function() {
expect(element(by.select('fruit')).getText()).
toEqual('applepearpeachbanana');
});

it('should find the selected option', function() {
expect(element(by.selectedOption('fruit')).getText()).toEqual('apple');
});

it('should find multiple selected options', function() {
browser.findElements(
by.selectedOption('dayColor.color')).then(function(arr) {
Expand All @@ -96,6 +107,8 @@ describe('locators', function() {
expect(arr[2].getText()).toBe('blue');
});
});


});

describe('by repeater', function() {
Expand Down
5 changes: 5 additions & 0 deletions testapp/form/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ <h4>Selects</h4>
<div ng-repeat="dayColor in dayColors">
<select ng-model="dayColor.color" ng-options="c for c in colors"></select>
</div>

<select ng-model="fruit" ng-options="fruit for fruit in fruits">
<option value="">{{defaultFruit}}</option>
</select>
<span>Fruit: {{fruit}}</span>
</div>

<div id="checkboxes">
Expand Down
5 changes: 5 additions & 0 deletions testapp/form/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ function FormCtrl($scope) {
$scope.aboutbox = "This is a text box";
$scope.color = "blue";
$scope.show = true;

$scope.colors = ['red', 'green', 'blue'];
$scope.dayColors = [{day: 'Mon', color: 'red'}, {day: 'Tue', color: 'green'}, {day: 'Wed', color: 'blue'}];

$scope.fruit = '';
$scope.defaultFruit = 'apple'
$scope.fruits = ['pear', 'peach', 'banana'];
}
FormCtrl.$inject = ['$scope'];

0 comments on commit 21264fd

Please sign in to comment.