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

Commit e45ceaa

Browse files
committed
fix(repeaters): allow finding all rows of a repeater
Now, finding an element with the strategy 'protractor.By.repeater()' returns a promise which will resolve to an array of WebElements, where each WebElement is a row in the repeater. Closes #149.
1 parent 8154adf commit e45ceaa

File tree

4 files changed

+142
-49
lines changed

4 files changed

+142
-49
lines changed

lib/clientsidescripts.js

+27
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,33 @@ clientSideScripts.findBindings = function() {
9797
return rows[index - 1];
9898
};
9999

100+
/**
101+
* Find all rows of an ng-repeat.
102+
*
103+
* arguments[0] {Element} The scope of the search.
104+
* arguments[1] {string} The text of the repeater, e.g. 'cat in cats'.
105+
*
106+
* @return {Array.<Element>} All rows of the repeater.
107+
*/
108+
clientSideScripts.findAllRepeaterRows = function() {
109+
var using = arguments[0] || document;
110+
var repeater = arguments[1];
111+
112+
var rows = [];
113+
var prefixes = ['ng-', 'ng_', 'data-ng-', 'x-ng-', 'ng\\:'];
114+
for (var p = 0; p < prefixes.length; ++p) {
115+
var attr = prefixes[p] + 'repeat';
116+
var repeatElems = using.querySelectorAll('[' + attr + ']');
117+
attr = attr.replace(/\\/g, '');
118+
for (var i = 0; i < repeatElems.length; ++i) {
119+
if (repeatElems[i].getAttribute(attr).indexOf(repeater) != -1) {
120+
rows.push(repeatElems[i]);
121+
}
122+
}
123+
}
124+
return rows;
125+
};
126+
100127
/**
101128
* Find an element within an ng-repeat by its row and column.
102129
*

lib/locators.js

+17
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,17 @@ ProtractorBy.prototype.textarea = function(model) {
110110
* // Returns a promise that resolves to an array of WebElements from a column
111111
* var ages = ptor.findElements(
112112
* protractor.By.repeater("cat in pets").column("{{cat.age}}"));
113+
* // Returns a promise that resolves to an array of WebElements containing
114+
* // all rows of the repeater.
115+
* var rows = ptor.findElements(protractor.By.repeater("cat in pets"));
113116
*/
114117
ProtractorBy.prototype.repeater = function(repeatDescriptor) {
115118
return {
119+
findArrayOverride: function(driver, using) {
120+
return driver.findElements(
121+
webdriver.By.js(clientSideScripts.findAllRepeaterRows),
122+
using, repeatDescriptor);
123+
},
116124
row: function(index) {
117125
return {
118126
findOverride: function(driver, using) {
@@ -137,6 +145,15 @@ ProtractorBy.prototype.repeater = function(repeatDescriptor) {
137145
return driver.findElements(
138146
webdriver.By.js(clientSideScripts.findRepeaterColumn),
139147
using, repeatDescriptor, binding);
148+
},
149+
row: function(index) {
150+
return {
151+
findOverride: function(driver, using) {
152+
return driver.findElement(
153+
webdriver.By.js(clientSideScripts.findRepeaterElement),
154+
using, repeatDescriptor, index, binding);
155+
}
156+
};
140157
}
141158
};
142159
}

spec/findelements_spec.js

+94-49
Original file line numberDiff line numberDiff line change
@@ -97,63 +97,108 @@ describe('finding elements', function() {
9797
});
9898
});
9999

100-
it('should find a repeater by partial match', function() {
101-
var fullMatch = ptor.findElement(
102-
protractor.By.repeater('baz in days | filter:\'T\'').
103-
row(1).column('{{baz}}'));
104-
expect(fullMatch.getText()).toEqual('Tue');
105-
106-
var partialMatch = ptor.findElement(
107-
protractor.By.repeater('baz in days').row(1).column('b'));
108-
expect(partialMatch.getText()).toEqual('Tue');
109-
110-
var partialRowMatch = ptor.findElement(
111-
protractor.By.repeater('baz in days').row(1));
112-
expect(partialRowMatch.getText()).toEqual('Tue');
113-
});
100+
describe('by repeater', function() {
101+
it('should find by partial match', function() {
102+
var fullMatch = ptor.findElement(
103+
protractor.By.repeater('baz in days | filter:\'T\'').
104+
row(1).column('{{baz}}'));
105+
expect(fullMatch.getText()).toEqual('Tue');
106+
107+
var partialMatch = ptor.findElement(
108+
protractor.By.repeater('baz in days').row(1).column('b'));
109+
expect(partialMatch.getText()).toEqual('Tue');
110+
111+
var partialRowMatch = ptor.findElement(
112+
protractor.By.repeater('baz in days').row(1));
113+
expect(partialRowMatch.getText()).toEqual('Tue');
114+
});
114115

115-
it('should find a repeater using data-ng-repeat', function() {
116-
var byRow =
117-
ptor.findElement(protractor.By.repeater('day in days').row(3));
118-
expect(byRow.getText()).toEqual('Wed');
116+
it('should return all rows when unmodified', function() {
117+
var all =
118+
ptor.findElements(protractor.By.repeater('dayColor in dayColors'));
119+
all.then(function(arr) {
120+
expect(arr.length).toEqual(3);
121+
expect(arr[0].getText()).toEqual('Mon red');
122+
expect(arr[1].getText()).toEqual('Tue green');
123+
expect(arr[2].getText()).toEqual('Wed blue');
124+
});
125+
});
119126

120-
var byCol =
121-
ptor.findElement(protractor.By.repeater('day in days').row(3).
122-
column('day'));
123-
expect(byCol.getText()).toEqual('Wed');
124-
});
127+
it('should return a single column', function() {
128+
var colors = ptor.findElements(
129+
protractor.By.repeater('dayColor in dayColors').column('color'));
130+
colors.then(function(arr) {
131+
expect(arr.length).toEqual(3);
132+
expect(arr[0].getText()).toEqual('red');
133+
expect(arr[1].getText()).toEqual('green');
134+
expect(arr[2].getText()).toEqual('blue');
135+
});
136+
});
125137

126-
it('should find a repeater using ng:repeat', function() {
127-
var byRow =
128-
ptor.findElement(protractor.By.repeater('bar in days').row(3));
129-
expect(byRow.getText()).toEqual('Wed');
138+
it('should return a single row', function() {
139+
var secondRow = ptor.findElement(
140+
protractor.By.repeater('dayColor in dayColors').row(2));
141+
expect(secondRow.getText()).toEqual('Tue green');
142+
});
130143

131-
var byCol =
132-
ptor.findElement(protractor.By.repeater('bar in days').row(3).
133-
column('bar'));
134-
expect(byCol.getText()).toEqual('Wed');
135-
});
144+
it('should return an individual cell', function() {
145+
var secondColor = ptor.findElement(
146+
protractor.By.repeater('dayColor in dayColors').
147+
row(2).
148+
column('color'));
136149

137-
it('should find a repeater using ng_repeat', function() {
138-
var byRow =
139-
ptor.findElement(protractor.By.repeater('foo in days').row(3));
140-
expect(byRow.getText()).toEqual('Wed');
150+
var secondColorByColumnFirst = ptor.findElement(
151+
protractor.By.repeater('dayColor in dayColors').
152+
column('color').
153+
row(2));
141154

142-
var byCol =
143-
ptor.findElement(protractor.By.repeater('foo in days').row(3).
144-
column('foo'));
145-
expect(byCol.getText()).toEqual('Wed');
146-
});
155+
expect(secondColor.getText()).toEqual('green');
156+
expect(secondColorByColumnFirst.getText()).toEqual('green');
157+
});
147158

148-
it('should find a repeater using x-ng-repeat', function() {
149-
var byRow =
150-
ptor.findElement(protractor.By.repeater('qux in days').row(3));
151-
expect(byRow.getText()).toEqual('Wed');
159+
it('should find a using data-ng-repeat', function() {
160+
var byRow =
161+
ptor.findElement(protractor.By.repeater('day in days').row(3));
162+
expect(byRow.getText()).toEqual('Wed');
152163

153-
var byCol =
154-
ptor.findElement(protractor.By.repeater('qux in days').row(3).
155-
column('qux'));
156-
expect(byCol.getText()).toEqual('Wed');
164+
var byCol =
165+
ptor.findElement(protractor.By.repeater('day in days').row(3).
166+
column('day'));
167+
expect(byCol.getText()).toEqual('Wed');
168+
});
169+
170+
it('should find using ng:repeat', function() {
171+
var byRow =
172+
ptor.findElement(protractor.By.repeater('bar in days').row(3));
173+
expect(byRow.getText()).toEqual('Wed');
174+
175+
var byCol =
176+
ptor.findElement(protractor.By.repeater('bar in days').row(3).
177+
column('bar'));
178+
expect(byCol.getText()).toEqual('Wed');
179+
});
180+
181+
it('should find using ng_repeat', function() {
182+
var byRow =
183+
ptor.findElement(protractor.By.repeater('foo in days').row(3));
184+
expect(byRow.getText()).toEqual('Wed');
185+
186+
var byCol =
187+
ptor.findElement(protractor.By.repeater('foo in days').row(3).
188+
column('foo'));
189+
expect(byCol.getText()).toEqual('Wed');
190+
});
191+
192+
it('should find using x-ng-repeat', function() {
193+
var byRow =
194+
ptor.findElement(protractor.By.repeater('qux in days').row(3));
195+
expect(byRow.getText()).toEqual('Wed');
196+
197+
var byCol =
198+
ptor.findElement(protractor.By.repeater('qux in days').row(3).
199+
column('qux'));
200+
expect(byCol.getText()).toEqual('Wed');
201+
});
157202
});
158203

159204
it('should determine if an element is present', function() {

testapp/app/partials/form.html

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
<span id="letterlist">{{check.w}}{{check.x}}{{check.y}}{{check.z}}</span>
2424

2525
<ul><li ng-repeat="baz in days | filter:'T'">{{baz}}</li></ul>
26+
<ul><li ng-repeat="dayColor in dayColors">
27+
<span>{{dayColor.day}}</span>
28+
<span>{{dayColor.color}}</span>
29+
</li></ul>
2630
<ul><li data-ng-repeat="day in days">{{day}}</li></ul>
2731
<ul><li ng:repeat="bar in days">{{bar}}</li></ul>
2832
<ul><li ng_repeat="foo in days">{{foo}}</li></ul>

0 commit comments

Comments
 (0)