Intern: loop on Promise.<Array.<leadfoot/Element>>

Let’s say I have the following DOM structure, for simplicity:

<div class='myparent'>
    <div class='child'>
        <div class="label">A</div>
        <div class="ico"/>
    </div>
    <div class='child'>
        <div class="label">B</div>
        <div class="ico"/>
    </div>
    <div class='child'>
        <div class="label">C</div>
        <div class="ico"/>
    </div>
</div>

I would like to loop within all child Element returned by the function findAllByCssSelector(‘.child’). In particular, I would click on the ico div subelement ONLY if the label of the div is B.

  • How to require modules for testing NodeJS with Intern JS?
  • How to test harmony / ES6 / ECMAScript 6 JavaScript?
  • Loading dependencies outside of project directory in the Intern
  • Unable to set baseUrl for intern-runner
  • setFindTimeout and pollUntil with Intern for elements that are not visible on initial page load
  • How do async tests work in intern?
  • I would remember, that findAllByCssSelector() returns Promise.<Array.<leadfoot/Element>>.

    Typically I should do something like:

    var my_label = null;
    this.remote
      .findAllByCssSelector('.my-selector').then(function (elementArray) {
          for(.....) {
            elementArray[i]
                .getVisibileText()
                  .then(function (text) {
                      if(text == my_label)
                        elementArray[i].findByCssSelector('.ico').click().end()
                  }
          }
    })
    

    I tried this code but did not work, because the elementArray[i] within the getVisibleText().then() function does not exist – it’s like I lose its reference. Furthermore, I need also that if the label is not found at the end of the loop, an exception should be thrown.

    How can I achieve that? Could anyone help, please?

  • How do async tests work in intern?
  • Unable to set baseUrl for intern-runner
  • Can't load modules for Intern testing while using Browserify
  • leadfoot vs webdriver.io - javascript client library for selenium WebDriver API
  • How can I get terminal size in a piped node.js process?
  • Loading dependencies outside of project directory in the Intern
  • One Solution collect form web for “Intern: loop on Promise.<Array.<leadfoot/Element>>”

    The simplest way to do this would be to use an Xpath expression to select the item directly, like:

    .findByXpath('//div[@class="child" and div[@class="label" and text()="B"]]/div[@class="ico"]')
    

    The expression above will find the first div with class “ico” that’s the child of a div with class “child” that has a child div with class “label” and text content “B”.


    Update

    Using an Xpath expression is almost always preferable to looping through elements using Leadfoot commands because it’s significantly more efficient, but if looping is desired for some reason, you can do something like:

    var my_label = null;
    this.remote
        .findAllByCssSelector('.my-selector')
        .then(function (elementArray) {
            return Promise.all(elementArray.map(function (element) {
                return element.getVisibleText()
                    .then(function (text) {
                        if (text === my_label) {
                            return element.findByCssSelector('.ico')
                                .then(function (ico) {
                                    return ico.click();
                                });
                        }
                    });
            });
        });
    

    A couple of key points to note:

    1. You need to return Promises/Commands from then callbacks when you’re performing async operations in the then callbacks
    2. Element methods (like element.findByCssSelector) return Promises, not Commands, so you can’t call click on the result.