How to use XPATH to search for a span with a class for Selenium Testing in JAVA

27,458

Solution 1

From the error you've mentioned, I suppose you are using textToBePresentInElement or textToBePresentInElementLocated or something related method under the ExpectedConditions class.

You can alternatively do this:
1- Wait for the visibility of the element using Explicit Wait
2- Retrieve the text
3- Assert/Compare the text with the value: '£163.06'.

You can try the below code that comprises of all above in order:

    String text_in_panel=null;
    try{
        //waiting 20 seconds for the visibility of the element
        WebDriverWait wait = new WebDriverWait(driver, 20);
        WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[contains(@class, 'panelMessage')]/span[1]")));

        //Retrieving the text from the element
        text_in_panel = element.getText();
    }catch(Throwable e){
        System.err.println("Element is not visible: "+e.getMessage());
    }

    //Comparing the text with the hard-coded value
    if(text_in_panel.equals("£163.06"))
        System.out.println("Text matches");
    else
        System.err.println("Text doesn't match");

[OR You can assert the values instead of comparing them, using the Assert class by importing import junit.framework.Assert;]

    //Assert the text with the hard-coded value
    try{
        Assert.assertEquals(text_in_panel, "£163.06");
        System.out.println("Text matches");
    }catch(Throwable e){
        System.err.println("Text doesn't match");
    }

Solution 2

Couple of things to keep that in mind:

  1. Testing the xpath on Chrome debugger of Firebug does not necessarily mean that the selector is going to return the target element uniquely. There might be some other elements hidden with same selector and webdriver will fail to find the target element in that case. For debugging purpose use findElements a see how many elements it returns.
  2. Element loading issue such as: visibility can also be another issue. That's why you need to make sure the element is present and visible. Use explicit wait

Try following xpaths

//span[@class='amountCharged']

If the class is not unique and you want to find the span depending on the div you can do the following:

//div[contains(@class,'panelMessage ')]//span[@class='amountCharged']
Share:
27,458
alyn000r
Author by

alyn000r

SOFTWARE ENGINEER :)

Updated on February 03, 2020

Comments

  • alyn000r
    alyn000r over 4 years

    I am working on a piece of code which wants me to select the span with the class amountCharged and get the value of that span to test it against the mock value. The problem that I am facing is that I cannot seem to select that span using XPath. I have tried multiple ways and still fail, I went on W3Schools and Stackoverflow questions but was unable to nail the syntax.

    Below is the error I am facing:

    org.openqa.selenium.TimeoutException: Timed out after 60 seconds waiting for text ('£163.06') to be present in element found by `By.xpath:`
    
     //span[contains(@class, 'amountCharged')]
    

    As you can see I am trying to use //span[contains(@class,'amountCharged')] as the XPATH, same issue with using "

    /descendant::span[contains(@class, 'amountCharged')]
    

    THE HTML STARTING FROM A PARENT DIV IS:

        <div class="panelMessage instructional" params="">    Total:         
     <span class="amountCharged">£163.06</span> quoted on          
    <span class="reservationTime">Tue, 29 Nov 2011 15:46 GMT</span> . </div>
        </div>        
    <div class="panelContent hideFocus noneBlock  " tabindex="-1" data-  context="panelContent">
    

    The JAVA code is:

       private static void elementShouldContain(String locator, String value, String errorMessage, long timeout) {
        String xpath = buildLocator(locator, "");
        WebDriverWait customWait = new WebDriverWait(webDriverInstance, timeout / 1000);
        try {
        customWait.until(ExpectedConditions.textToBePresentInElement(By.xpath(xpath), value));
        } catch (Exception e) {
            // Handles the specific exception, except that the message is null, in which case throws a regular SeleniumException
            if (errorMessage != null)
                throw new CustomSeleniumException(errorMessage, e);
            else
                throw new SeleniumException(e);
        }
    }
    

    what am I missing please help.

    Thank You

    • kjhughes
      kjhughes over 9 years
      It'd be good to show the HTML from which your XPath is intended to select.
    • Master Slave
      Master Slave over 9 years
      your error message indicates that it can't find the particular text, but it does find the element
    • alyn000r
      alyn000r over 9 years
      I have pasted the HTML, and the text 163.06 is there
    • Saifur
      Saifur over 9 years
      Is there more element with amountCharged name present?
    • alyn000r
      alyn000r over 9 years
      No, in the entire HTML there is just one span with this class. And it selects the span when I do it through chrome reg x checker
    • Saifur
      Saifur over 9 years
      And, I want to see how you get the text as well. Meaning what are you using to get the span text
    • alyn000r
      alyn000r over 9 years
      /descendant::span[contains(@class, 'amountCharged')]/text()[last()] I tried this and compared it to a hard coded String "£163.06"
  • alyn000r
    alyn000r over 9 years
    I actually got this to work using Chrome debugger but my test still thinks that it is not there. /descendant::span[contains(@class, 'amountCharged')]/text()[last()]
  • Saifur
    Saifur over 9 years
    I would like to see the test code and stacktrace you get then
  • Mathias Müller
    Mathias Müller over 9 years
    @alyn000r If you care about getting an answer, show the complete HTML and test code. We don't like being in the dark (and neither would you, I think).
  • alyn000r
    alyn000r over 9 years
    I have added the JAVA code here too sorry for not adding it earlier. I cannot put the entire HTML due to company policies.