Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Selenium's ByChained class really works?

I am very confused with what the documentation for ByChained class mentions. It says:

Mechanism used to locate elements within a document using a series of other lookups. This class will find all DOM elements that matches each of the locators in sequence, e.g. driver.findElements(new ByChained(by1, by2)) will find all elements that match by2 and appear under an element that matches by1.

There is also an issue for selenium on code.google.com, raised for ByChained class where someone has commented saying it's meant to be used to find element/elements using several locators.

I don't get it. Why should by1 and by2 be locators of two different elements? When I initally came across this class I felt that it will help in locating element(s) by using different locators. So that if one locator does not work, the next would work. But when I practically used this class it behaved very weirdly and threw NoSuchElementException all the time.

For example, if my html is:

<html>
  <body>
    <div id="details">
      <input id="firstName" class="personName" type="text"/>
    </div>
  </body>
</html>

I want to find the input field by using two locators in ByChained:
1. using By.id("firstName")
2. using By.className("personName")

So my code becomes:

By myBy = new ByChained(By.id("firstName"),By.className("personName"));
driver.findElement(myBy);

On execution, I got NoSuchElementException. I was expecting that if my first By did not work, then it will find the element with the next By in the series.

Can someone please explain how this class works with an example and in which scenarios it could be used?

like image 360
Abhijeet Vaikar Avatar asked Mar 13 '14 14:03

Abhijeet Vaikar


1 Answers

What this class does is allow you to locate an element using its heirarchy in the dom.

lets say for some reason you have the following html:

<html>
    <body>
        <div id="details">
            <input id="firstName" class="personName" type="text"/>
        </div>
        <input id="firstName" class="personName" type="text"/>
    </body>
</html>

and you want to get the element that is between the div rather than the one on its own. You can use the ByChained by to specify that you want that element by doing the following:

new ByChained(By.id("details"),By.id("firstName"));

What happens is that it finds the first element then searches underneath that in the dom heirarchy for the selector that comes next in the list. Basically this By is just a nice clean way of no longer having to do the following:

details = driver.findElement(By.id("details"));
input = details.findElement(By.id("firstName"));
like image 66
Paul Harris Avatar answered Sep 30 '22 10:09

Paul Harris