Search code examples
javaseleniumselenium-webdriverpageobjectsfindby

Selenium can't find element by @FindBys annotation in case of two conditions


I have a text element on the page with properties:

Web element property

And I'm trying to get this element using FindBys annotation:

@FindBys({@FindBy(tagName = "h5"),@FindBy(id = "email_label")})
private WebElement EmailLabel;

but getting error: org.openqa.selenium.NoSuchElementException: Cannot locate an element using By.chained({By.tagName: h5,By.id: email_label})

At the same time element is found properly if use just one condition:

@FindBys({@FindBy(id = "email_label")})
private WebElement EmailLabel;

or

@FindBys({@FindBy(tagName = "h5")})
private WebElement EmailLabel;

I use:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
</dependency>
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-chrome-driver</artifactId>
    <version>3.141.59</version>
</dependency>

Solution

  • FindBys Annotation

    FindBys are used to mark a field on a to indicate that lookup should use a series of @FindBy tags in a chain as described in ByChained. As an example:

    @FindBys({@FindBy(id = "foo"),
          @FindBy(className = "bar")})
    

    Class ByChained

    ByChained 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, Asan example:

    driver.findElements(new ByChained(by1, by2))
    

    The above line of code will find all elements that match by2 and appear under an element that matches by1. So essentially you shouldn't use both the by on the same node but one by for the parent node and the other for the child node and you can use the following Locator Strategy:

    @FindBys({@FindBy(tagName = "h5"), @FindBy(tagName = "strong")})
    private WebElement EmailLabel;
    

    Ideally, to locate the <span> with text as What's your email address? you can use either of the following Locator Strategies:

    • Using css:

      @FindBys({@FindBy(css  = "h5#email_label>strong"), @FindBy(tagName = "span")})
      private WebElement EmailLabel;
      
    • Using xpath:

      @FindBys({@FindBy(xpath  = "//h5[@id='email_label']/strong"), @FindBy(xpath = "//span[contains(., 'your email address')]")})
      private WebElement EmailLabel;