<commit_before>var webdriver = require('selenium-webdriver');
var log = require('./logger.js');
var clientSideScripts = require('./clientsidescripts.js');

var WEB_ELEMENT_FUNCTIONS = [
  'click', 'sendKeys', 'getTagName', 'getCssValue', 'getAttribute', 'getText',
  'getSize', 'getLocation', 'isEnabled', 'isSelected', 'submit', 'clear',
  'isDisplayed', 'getOuterHtml', 'getInnerHtml', 'getId', 'getRawId'];

/**
 * ElementArrayFinder is used for operations on an array of elements (as opposed
 * to a single element).
 *
 * The ElementArrayFinder is used to set up a chain of conditions that identify
 * an array of elements. In particular, you can call all(locator) and
 * filter(filterFn) to return a new ElementArrayFinder modified by the
 * conditions, and you can call get(index) to return a single ElementFinder at
 * position 'index'.
 *
 * Similar to jquery, ElementArrayFinder will search all branches of the DOM
 * to find the elements that satisfy the conditions (i.e. all, filter, get).
 * However, an ElementArrayFinder will not actually retrieve the elements until
 * an action is called, which means it can be set up in helper files (i.e.
 * page objects) before the page is available, and reused as the page changes.
 *
 * You can treat an ElementArrayFinder as an array of WebElements for most
 * purposes, in particular, you may perform actions (i.e. click, getText) on
 * them as you would an array of WebElements. The action will apply to
 * every element identified by the ElementArrayFinder. ElementArrayFinder
 * extends Promise, and once an action is performed on an ElementArrayFinder,
 * the latest result can be accessed using then, and will be returned as an
 * array of the results; the array has length equal to the length of the
 * elements found by the ElementArrayFinder and each result represents the
 * result of performing the action on the element. Unlike a WebElement, an
 * ElementArrayFinder will wait for the angular app to settle before
 * performing finds or actions.
 *
 * @alias element.all(locator)
 * @view
 * <ul class="items">
 *   <li>First</li>
 *   <li>Second</li>
 *   <li>Third</li>
 * </ul>
 *
 * @example
 * element.all(by.css('.items li')).then(function(items) {
 *   expect(items.length).toBe(3);
 *   expect(items[0].getText()).toBe('First');
 * });
 *
 * @constructor
 * @param {Protractor} ptor A protractor instance.
 * @param {function(): Array.<webdriver.WebElement>} getWebElements A function
 *    that returns a list of the underlying Web Elements.
 * @param {webdriver.Locator} locator The most relevant locator. It is only
 *    used for error reporting and ElementArrayFinder.locator.
 * @param {Array.<webdriver.promise.Promise>} opt_actionResults An array
 *    of promises which will be retrieved with then. Resolves to the latest
 *    action result, or null if no action has been called.
 * @return {ElementArrayFinder}
 */
var ElementArrayFinder = function(ptor, getWebElements, locator, opt_actionResults) {
  this.ptor_ = ptor;
  this.getWebElements = getWebElements || null;
  this.actionResults_ = opt_actionResults;
  this.locator_ = locator;
};

exports.ElementArrayFinder = ElementArrayFinder;

WEB_ELEMENT_FUNCTIONS.forEach(function(fnName) {
  ElementArrayFinder.prototype[fnName] = function() {
    var args = arguments;
    var actionFn = function(webElem) {
      return webElem[fnName].apply(webElem, args);
    };
    return this.applyAction_(actionFn);
  };
});

/**
 * Create a shallow copy of ElementArrayFinder.
 *
 * @return {!ElementArrayFinder} A shallow copy of this.
 */
ElementArrayFinder.prototype.clone = function() {
  // A shallow copy is all we need since the underlying fields can never be
  // modified. (Locator can be modified by the user, but that should
  // rarely/never happen and it doesn't affect functionalities).
  return new ElementArrayFinder(
    this.ptor_, this.getWebElements, this.locator_, this.actionResults_);
};

/**
 * Calls to ElementArrayFinder may be chained to find an array of elements
 * using the current elements in this ElementArrayFinder as the starting point.
 * This function returns a new ElementArrayFinder which would contain the
 * children elements found (and could also be empty).
 *
 * @alias element.all(locator).all(locator)
 * @view
 * <div id='id1' class="parent">
 *   <ul>
 *     <li class="foo">1a</li>
 *     <li class="baz">1b</li>
 *   </ul>
 * </div>
 * <div id='id2' class="parent">
 *   <ul>
 *     <li class="foo">2a</li>
 *     <li class="bar">2b</li>
 *   </ul>
 * </div>
 *
 * @example
 * var foo = element.all(by.css('.parent')).all(by.css('.foo'))
 * expect(foo.getText()).toEqual(['1a', '2a'])
 * var baz = element.all(by.css('.parent')).all(by.css('.baz'))
 * expect(baz.getText()).toEqual(['1b'])
 * var nonexistent = element.all(by.css('.parent')).all(by.css('.NONEXISTENT'))
 * expect(nonexistent.getText()).toEqual([''])
 *
 * @param {webdriver.Locator} subLocator
 * @return {ElementArrayFinder}
 */
ElementArrayFinder.prototype.all = function(locator) {
  var self = this;
  var ptor = this.ptor_;
  var getWebElements = function() {
    if (self.getWebElements === null) {
      // This is the first time we are looking for an element
      return ptor.waitForAngular().then(function() {
        if (locator.findElementsOverride) {
          return locator.findElementsOverride(ptor.driver, null, ptor.rootEl);
        } else {
          return ptor.driver.findElements(locator);
        }
      });
    } else {
      return self.getWebElements().then(function(parentWebElements) {
        // For each parent web element, find their children and construct a
        // list of Promise<List<child_web_element>>
        var childrenPromiseList = parentWebElements.map(function(parentWebElement) {
          return locator.findElementsOverride ?
            locator.findElementsOverride(ptor.driver, parentWebElement, ptor.rootEl) :
            parentWebElement.findElements(locator);
        });

        // Resolve the list of Promise<List<child_web_elements>> and merge into
        // a single list
        return webdriver.promise.all(childrenPromiseList).then(function(resolved) {
          return resolved.reduce(function(childrenList, resolvedE) {
            return childrenList.concat(resolvedE);
          }, []);
        });
      });
    }
  };
  return new ElementArrayFinder(this.ptor_, getWebElements, locator);
};

/**
 * Apply a filter function to each element within the ElementArrayFinder. Returns
 * a new ElementArrayFinder 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.
 * This does not actually retrieve the underlying list of elements, so it can
 * be used in page objects.
 *
 * @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 can either return a boolean or a promise that resolves to a boolean.
 * @return {!ElementArrayFinder} A ElementArrayFinder that represents an array
 *     of element that satisfy the filter function.
 */
ElementArrayFinder.prototype.filter = function(filterFn) {
  var self = this;<commit_msg>docs(filter): fix ElementArrayFinder#filter example docs<commit_after>var webdriver = require('selenium-webdriver');
var log = require('./logger.js');
var clientSideScripts = require('./clientsidescripts.js');

var WEB_ELEMENT_FUNCTIONS = [
  'click', 'sendKeys', 'getTagName', 'getCssValue', 'getAttribute', 'getText',
  'getSize', 'getLocation', 'isEnabled', 'isSelected', 'submit', 'clear',
  'isDisplayed', 'getOuterHtml', 'getInnerHtml', 'getId', 'getRawId'];

/**
 * ElementArrayFinder is used for operations on an array of elements (as opposed
 * to a single element).
 *
 * The ElementArrayFinder is used to set up a chain of conditions that identify
 * an array of elements. In particular, you can call all(locator) and
 * filter(filterFn) to return a new ElementArrayFinder modified by the
 * conditions, and you can call get(index) to return a single ElementFinder at
 * position 'index'.
 *
 * Similar to jquery, ElementArrayFinder will search all branches of the DOM
 * to find the elements that satisfy the conditions (i.e. all, filter, get).
 * However, an ElementArrayFinder will not actually retrieve the elements until
 * an action is called, which means it can be set up in helper files (i.e.
 * page objects) before the page is available, and reused as the page changes.
 *
 * You can treat an ElementArrayFinder as an array of WebElements for most
 * purposes, in particular, you may perform actions (i.e. click, getText) on
 * them as you would an array of WebElements. The action will apply to
 * every element identified by the ElementArrayFinder. ElementArrayFinder
 * extends Promise, and once an action is performed on an ElementArrayFinder,
 * the latest result can be accessed using then, and will be returned as an
 * array of the results; the array has length equal to the length of the
 * elements found by the ElementArrayFinder and each result represents the
 * result of performing the action on the element. Unlike a WebElement, an
 * ElementArrayFinder will wait for the angular app to settle before
 * performing finds or actions.
 *
 * @alias element.all(locator)
 * @view
 * <ul class="items">
 *   <li>First</li>
 *   <li>Second</li>
 *   <li>Third</li>
 * </ul>
 *
 * @example
 * element.all(by.css('.items li')).then(function(items) {
 *   expect(items.length).toBe(3);
 *   expect(items[0].getText()).toBe('First');
 * });
 *
 * @constructor
 * @param {Protractor} ptor A protractor instance.
 * @param {function(): Array.<webdriver.WebElement>} getWebElements A function
 *    that returns a list of the underlying Web Elements.
 * @param {webdriver.Locator} locator The most relevant locator. It is only
 *    used for error reporting and ElementArrayFinder.locator.
 * @param {Array.<webdriver.promise.Promise>} opt_actionResults An array
 *    of promises which will be retrieved with then. Resolves to the latest
 *    action result, or null if no action has been called.
 * @return {ElementArrayFinder}
 */
var ElementArrayFinder = function(ptor, getWebElements, locator, opt_actionResults) {
  this.ptor_ = ptor;
  this.getWebElements = getWebElements || null;
  this.actionResults_ = opt_actionResults;
  this.locator_ = locator;
};

exports.ElementArrayFinder = ElementArrayFinder;

WEB_ELEMENT_FUNCTIONS.forEach(function(fnName) {
  ElementArrayFinder.prototype[fnName] = function() {
    var args = arguments;
    var actionFn = function(webElem) {
      return webElem[fnName].apply(webElem, args);
    };
    return this.applyAction_(actionFn);
  };
});

/**
 * Create a shallow copy of ElementArrayFinder.
 *
 * @return {!ElementArrayFinder} A shallow copy of this.
 */
ElementArrayFinder.prototype.clone = function() {
  // A shallow copy is all we need since the underlying fields can never be
  // modified. (Locator can be modified by the user, but that should
  // rarely/never happen and it doesn't affect functionalities).
  return new ElementArrayFinder(
    this.ptor_, this.getWebElements, this.locator_, this.actionResults_);
};

/**
 * Calls to ElementArrayFinder may be chained to find an array of elements
 * using the current elements in this ElementArrayFinder as the starting point.
 * This function returns a new ElementArrayFinder which would contain the
 * children elements found (and could also be empty).
 *
 * @alias element.all(locator).all(locator)
 * @view
 * <div id='id1' class="parent">
 *   <ul>
 *     <li class="foo">1a</li>
 *     <li class="baz">1b</li>
 *   </ul>
 * </div>
 * <div id='id2' class="parent">
 *   <ul>
 *     <li class="foo">2a</li>
 *     <li class="bar">2b</li>
 *   </ul>
 * </div>
 *
 * @example
 * var foo = element.all(by.css('.parent')).all(by.css('.foo'))
 * expect(foo.getText()).toEqual(['1a', '2a'])
 * var baz = element.all(by.css('.parent')).all(by.css('.baz'))
 * expect(baz.getText()).toEqual(['1b'])
 * var nonexistent = element.all(by.css('.parent')).all(by.css('.NONEXISTENT'))
 * expect(nonexistent.getText()).toEqual([''])
 *
 * @param {webdriver.Locator} subLocator
 * @return {ElementArrayFinder}
 */
ElementArrayFinder.prototype.all = function(locator) {
  var self = this;
  var ptor = this.ptor_;
  var getWebElements = function() {
    if (self.getWebElements === null) {
      // This is the first time we are looking for an element
      return ptor.waitForAngular().then(function() {
        if (locator.findElementsOverride) {
          return locator.findElementsOverride(ptor.driver, null, ptor.rootEl);
        } else {
          return ptor.driver.findElements(locator);
        }
      });
    } else {
      return self.getWebElements().then(function(parentWebElements) {
        // For each parent web element, find their children and construct a
        // list of Promise<List<child_web_element>>
        var childrenPromiseList = parentWebElements.map(function(parentWebElement) {
          return locator.findElementsOverride ?
            locator.findElementsOverride(ptor.driver, parentWebElement, ptor.rootEl) :
            parentWebElement.findElements(locator);
        });

        // Resolve the list of Promise<List<child_web_elements>> and merge into
        // a single list
        return webdriver.promise.all(childrenPromiseList).then(function(resolved) {
          return resolved.reduce(function(childrenList, resolvedE) {
            return childrenList.concat(resolvedE);
          }, []);
        });
      });
    }
  };
  return new ElementArrayFinder(this.ptor_, getWebElements, locator);
};

/**
 * Apply a filter function to each element within the ElementArrayFinder. Returns
 * a new ElementArrayFinder 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.
 * This does not actually retrieve the underlying list of elements, so it can
 * be used in page objects.
 *
 * @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';
 *   });
 * }).first().click();
 *
 * @param {function(ElementFinder, number): webdriver.WebElement.Promise} filterFn
 *     Filter function that will test if an element should be returned.
 *     filterFn can either return a boolean or a promise that resolves to a boolean.
 * @return {!ElementArrayFinder} A ElementArrayFinder that represents an array
 *     of element that satisfy the filter function.
 */
ElementArrayFinder.prototype.filter = function(filterFn) {
  var self = this;
{'fraction_non_alphanumeric': 0.11793404020035127, 'fraction_numerical': 0.0014961295778312626, 'mean_word_length': 3.8345911949685534, 'pattern_counts': {'":': 0, '<': 79, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6836185', 'n_tokens_mistral': 4373, 'n_tokens_neox': 4432, 'n_words': 1470}