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

Commit

Permalink
feat(protractor): implement reduce and filter for ElementArrayFinder
Browse files Browse the repository at this point in the history
See #877
  • Loading branch information
hankduan committed Jun 19, 2014
1 parent 1848111 commit c892c2a
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
86 changes: 86 additions & 0 deletions lib/protractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,92 @@ var buildElementHelper = function(ptor) {
});
};

/**
* Apply a filter function to each element found using the locator. Returns
* promise of a new array with all elements that pass the filter function. The
* filter function receives the ElementFinder as the first argument
* and the index as a second arg.
*
* @alias element.all(locator).filter(filterFn)
* @view
* <ul class="items">
* <li class="one">First</li>
* <li class="two">Second</li>
* <li class="three">Third</li>
* </ul>
*
* @example
* element.all(by.css('.items li')).filter(function(elem, index) {
* return elem.getText().then(function(text) {
* return text === 'Third';
* });
* }).then(function(filteredElements) {
* filteredElements[0].click();
* });
*
* @param {function(ElementFinder, number): webdriver.WebElement.Promise} filterFn
* Filter function that will test if an element should be returned.
* filterFn should return a promise that resolves to a boolean.
* @return {!webdriver.promise.Promise} A promise that resolves to an array
* of ElementFinders that satisfy the filter function.
*/
ElementArrayFinder.prototype.filter = function(filterFn) {
return this.asElementFinders_().then(function(arr) {
var list = [];
arr.forEach(function(elementFinder, index) {
filterFn(elementFinder, index).then(function(satisfies) {
if (satisfies) {
list.push(elementFinder);
}
});
});
return list;
});
};

/**
* Apply a reduce function against an accumulator and every element found
* using the locator (from left-to-right). The reduce function has to reduce
* every element into a single value (the accumulator). Returns promise of
* the accumulator. The reduce function receives the accumulator, current
* ElementFinder, the index, and the entire array of ElementFinders,
* respectively.
*
* @alias element.all(locator).reduce(reduceFn)
* @view
* <ul class="items">
* <li class="one">First</li>
* <li class="two">Second</li>
* <li class="three">Third</li>
* </ul>
*
* @example
* var value = element.all(by.css('.items li')).reduce(function(acc, elem) {
* return elem.getText().then(function(text) {
* return acc + text + ' ';
* });
* });
*
* expect(value).toEqual('First Second Third ');
*
* @param {function(number, ElementFinder, number, Array.<ElementFinder>)}
* reduceFn Reduce function that reduces every element into a single value.
* @param {*} initialValue Initial value of the accumulator.
* @return {!webdriver.promise.Promise} A promise that resolves to the final
* value of the accumulator.
*/
ElementArrayFinder.prototype.reduce = function(reduceFn, initialValue) {
var valuePromise = webdriver.promise.fulfilled(initialValue);
return this.asElementFinders_().then(function(arr) {
arr.forEach(function(elementFinder, index) {
valuePromise = valuePromise.then(function(value) {
return reduceFn(value, elementFinder, index, arr);
});
});
return valuePromise;
});
};

/**
* The ElementFinder can be treated as a WebElement for most purposes, in
* particular, you may perform actions (i.e. click, getText) on them as you
Expand Down
31 changes: 31 additions & 0 deletions spec/basic/elements_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,37 @@ describe('ElementFinder', function() {
expect(labels).toEqual([1, 2, 3, 4, 5, 6, 7]);
});

it('should filter elements', function() {
browser.get('index.html#/form');
var count = element.all(by.css('.menu li a')).filter(function(elem) {
return elem.getText().then(function(text) {
return text === 'bindings';
});
}).then(function(filteredElements) {
return filteredElements.length;
});

expect(count).toEqual(1);
});

it('should reduce elements', function() {
browser.get('index.html#/form');
var value = element.all(by.css('.menu li a')).
reduce(function(currentValue, elem, index, elemArr) {
return elem.getText().then(function(text) {
return currentValue + index + '/' + elemArr.length + ': ' + text + '\n';
});
}, '');

expect(value).toEqual('0/7: repeater\n' +
'1/7: bindings\n' +
'2/7: form\n' +
'3/7: async\n' +
'4/7: conflict\n' +
'5/7: polling\n' +
'6/7: animation\n');
});

it('should export an isPresent helper', function() {
browser.get('index.html#/form');

Expand Down

0 comments on commit c892c2a

Please sign in to comment.