@@ -327,6 +327,92 @@ var buildElementHelper = function(ptor) {
327
327
} ) ;
328
328
} ;
329
329
330
+ /**
331
+ * Apply a filter function to each element found using the locator. Returns
332
+ * promise of a new array with all elements that pass the filter function. The
333
+ * filter function receives the ElementFinder as the first argument
334
+ * and the index as a second arg.
335
+ *
336
+ * @alias element.all(locator).filter(filterFn)
337
+ * @view
338
+ * <ul class="items">
339
+ * <li class="one">First</li>
340
+ * <li class="two">Second</li>
341
+ * <li class="three">Third</li>
342
+ * </ul>
343
+ *
344
+ * @example
345
+ * element.all(by.css('.items li')).filter(function(elem, index) {
346
+ * return elem.getText().then(function(text) {
347
+ * return text === 'Third';
348
+ * });
349
+ * }).then(function(filteredElements) {
350
+ * filteredElements[0].click();
351
+ * });
352
+ *
353
+ * @param {function(ElementFinder, number): webdriver.WebElement.Promise } filterFn
354
+ * Filter function that will test if an element should be returned.
355
+ * filterFn should return a promise that resolves to a boolean.
356
+ * @return {!webdriver.promise.Promise } A promise that resolves to an array
357
+ * of ElementFinders that satisfy the filter function.
358
+ */
359
+ ElementArrayFinder . prototype . filter = function ( filterFn ) {
360
+ return this . asElementFinders_ ( ) . then ( function ( arr ) {
361
+ var list = [ ] ;
362
+ arr . forEach ( function ( elementFinder , index ) {
363
+ filterFn ( elementFinder , index ) . then ( function ( satisfies ) {
364
+ if ( satisfies ) {
365
+ list . push ( elementFinder ) ;
366
+ }
367
+ } ) ;
368
+ } ) ;
369
+ return list ;
370
+ } ) ;
371
+ } ;
372
+
373
+ /**
374
+ * Apply a reduce function against an accumulator and every element found
375
+ * using the locator (from left-to-right). The reduce function has to reduce
376
+ * every element into a single value (the accumulator). Returns promise of
377
+ * the accumulator. The reduce function receives the accumulator, current
378
+ * ElementFinder, the index, and the entire array of ElementFinders,
379
+ * respectively.
380
+ *
381
+ * @alias element.all(locator).reduce(reduceFn)
382
+ * @view
383
+ * <ul class="items">
384
+ * <li class="one">First</li>
385
+ * <li class="two">Second</li>
386
+ * <li class="three">Third</li>
387
+ * </ul>
388
+ *
389
+ * @example
390
+ * var value = element.all(by.css('.items li')).reduce(function(acc, elem) {
391
+ * return elem.getText().then(function(text) {
392
+ * return acc + text + ' ';
393
+ * });
394
+ * });
395
+ *
396
+ * expect(value).toEqual('First Second Third ');
397
+ *
398
+ * @param {function(number, ElementFinder, number, Array.<ElementFinder>) }
399
+ * reduceFn Reduce function that reduces every element into a single value.
400
+ * @param {* } initialValue Initial value of the accumulator.
401
+ * @return {!webdriver.promise.Promise } A promise that resolves to the final
402
+ * value of the accumulator.
403
+ */
404
+ ElementArrayFinder . prototype . reduce = function ( reduceFn , initialValue ) {
405
+ var valuePromise = webdriver . promise . fulfilled ( initialValue ) ;
406
+ return this . asElementFinders_ ( ) . then ( function ( arr ) {
407
+ arr . forEach ( function ( elementFinder , index ) {
408
+ valuePromise = valuePromise . then ( function ( value ) {
409
+ return reduceFn ( value , elementFinder , index , arr ) ;
410
+ } ) ;
411
+ } ) ;
412
+ return valuePromise ;
413
+ } ) ;
414
+ } ;
415
+
330
416
/**
331
417
* The ElementFinder can be treated as a WebElement for most purposes, in
332
418
* particular, you may perform actions (i.e. click, getText) on them as you
0 commit comments