Search code examples
javaseleniumxpathwebdriverfindelement

WebElement.findElement is not finding child element


I am trying to get child element (Card Number) from an html codes where html tags and class names are same. Below is the html code snippet

<li class="paymentMethods-stored">  
    <li class="paymentMethod">
        <div class="stored-card-details">
            <span class="body-2">Name: </span>
            <span class="body-2 body-2-md"> VISA</span>
        <p>
            <span class="body-2">Number:</span>
            <span class="body-2 body-2-md"> ************4305</span>
        </p>
        <p>
            <span class="body-2">Expiry:</span>
            <span class="body-2 body-2-md"> 03/2030</span>
        </p>
        </div>
    </li>
    <li class="paymentMethod">
        <div class="stored-card-details">
            <span class="body-2">Name: </span>
            <span class="body-2 body-2-md"> VISA</span>
        <p>
            <span class="body-2">Number:</span>
            <span class="body-2 body-2-md"> ************4111</span>
        </p>
        <p>
            <span class="body-2">Expiry:</span>
            <span class="body-2 body-2-md"> 04/2031</span>
        </p>
        </div>
    </li>
</li>

Below is the identifiers I tried. But both returned first card number "************4305".

@FindBy(xpath = "//li[@class='paymentMethods-stored']//li[@class='paymentMethod']")
private WebElement firstSavedCard;
        
@FindBy(xpath = "(//li[@class='paymentMethods-stored']//li[@class='paymentMethod'])[2]")
private WebElement secondSavedCard; 
        
String firstCard=firstSavedCard.findElement(By.xpath("//*[@class='stored-card-details']/p[1]/span[2]")).getText();
String secondCard=secondSavedCard.findElement(By.xpath("//*[@class='stored-card-details']/p[1]/span[2]")).getText();

        

Other options tried: this also returned first card number "************4305".

secondSavedCard.findElement(By.xpath("/p[1]/span[2]")).getText();
secondSavedCard.findElement(By.xpath(".//*[@class='stored-card-details']/p[1]/span[2]")).getText()

Solution

  • As @Robbie Wareham mentioned in his answer //* would initiate the search from the root element, but as as your code block you need to search from the already found relative element.

    To find the cardnumber as an alternative you can use the following locator strategies:

    @FindBy(xpath = "//li[@class='paymentMethods-stored']//following::li[1]//p//span[contains(., 'Number')]//following-sibling::span[1]")
    private WebElement firstSavedCardNumber;
    
    @FindBy(xpath = "(//li[@class='paymentMethods-stored']//following::li[2]//p//span[contains(., 'Number')]//following-sibling::span[1]")
    private WebElement secondSavedCardNumber;