4

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.

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?

Bruno Bruzzano
  • 477
  • 7
  • 21
  • So? Just place the loop in the promise callback. Do you know how to access the array? Please post your current attempt at code (even if not working) – Bergi Aug 28 '15 at 21:47

1 Answers1

5

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.
jason0x43
  • 3,363
  • 1
  • 16
  • 15
  • Unfortunately `ico` and `label` divs are siblings, as shown above. Furthermore I would say that the the snippet above is really simplified, since there could be more divs between `child` and `labe|ico`. However thanks for the effort. By the way, here the question is how to loop into a `Promise.>`, and keep trace of an Element if a certain condition is verified. I update the first post for explain my self better. – Bruno Bruzzano Aug 29 '15 at 08:12
  • The Xpath statement above assumes that the `ico` and `label` divs are siblings -- that's the point. It works with the snippet provided in the question, and can be easily modified to handle a more complex structure. – jason0x43 Aug 29 '15 at 12:57
  • @jason0x43 sorry, did not go through your answer properly, after I edited my answer to use `map` became a duplicate of yours, hence deleted mine :) – mido Aug 31 '15 at 02:58
  • Tanks Jason! At the end of the story I used the xpath selector, which is much simpler and my code is still readable :) Thanks! However, I'll keep in consideration the Promise array loop for an eventual future use. – Bruno Bruzzano Aug 31 '15 at 08:45