Tony
Tony

Reputation: 1165

Waiting for the visibility of an element

Using Java and Selenium.

We have a method waitForXPathVisibility(xpath) which eventually ends up calling a wait.untilExpectedConditions... visibilityOfElement. This method works fine. I just abbreviated it here. So trus me that waitForXpathVisibility(xpath) will wait until it is visible.

So we have a page of medical specialties. It was originally just in English. So if you search for "neuro", the HTML will look something like

<ul id="ui-id-1" tabindex="0" class="ui-menu ui-widget ui-widget-content ui-autocomplete ui-front" style="width: 476.672px; position: relative; top: -1005px; left: 542.828px; display: none;">
 <LI class="ui-menu-item"> Neurology</Li>
 <LI class="ui-menu-item"> Neuro Surgeon </li>
 </UL>

then they added Spanish, so not still all results will return but only the Spanish will be visible. A new

to the bottom of the previous one. And the UL's, even the displayed one, have "display; none" as part of the style id.

Previously, when doing a search, I would do a

 waitForXpathVisibility("//li[@class='ui-menu-item']");

which would return. But the search always finds the first one, so the xpath above will point to the first English one, which will no longer be visible, so it will time out.

Is there a way to wait for any element matching an xpath to be visible? Note that visibilityOfAllElements() will not work, because they will not all be visible.

I suppose what could be done is beforehand get a count of all the elements with @id and with "width" as part of the style. "display; none" will not work because there are other s with this value. Then do the search and wait for the number of s to increase by 1, get the id of the last and then wait for an

  • underneath it to become visible, but that seems a bit much. There should be someway to wait for a visible
  • ? I could then return its parent

    Upvotes: 2

    Views: 881

  • Answers (2)

    JeffC
    JeffC

    Reputation: 25611

    I think what you are looking for is

    //ul[contains(@class,'ui-menu')][last()]/li
    ^ finds a UL
        ^ that contains the 'ui-menu' class
                                    ^ get the last one (the one that contains visible elements)
                                            ^ get the LI children
    

    You should be able to wait until all of those are visible using visibilityOfAllElements.


    Side note... don't write a method waitForXPathVisibility() that is restricted to only XPath. That makes it to where you have to write a method for each locator type you use (CSS selector, name, id, etc.). Instead take a By as a parameter and make it generic. See below.

    public void waitForVisibilityOfElement(By locator)
    {
        new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(locator));
    }
    

    You can also write one for more than one element

    public void waitForVisibilityOfElements(By locator)
    {
        new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(locator));
    }
    

    and you use it like

    By someElementLocator = By.id("someId");
    By someElementLocator = By.xpath("//ul[contains(@class,'ui-menu')][last()]/li"); // or this
    By someElementLocator = By.cssSelector("ul.ui-menu"); // or this
    waitForVisibilityOfElement(someElementLocator);
    

    Upvotes: 1

    KunduK
    KunduK

    Reputation: 33384

    Use JavaScript executor to get the hidden value. If you want to get the value of Neurologa Try below code.Hope this help.

    WebElement element=driver.findElement(By.xpath("(//ul[@id='ui-id-2']/li[@class='ui-menu-item'])[1]"));
    JavascriptExecutor js = (JavascriptExecutor) driver;
    String output=(String) js.executeScript("return arguments[0].innerHTML;", element);
    System.out.println(output);
    

    OR

    WebElement element=driver.findElement(By.xpath("//li[@class='ui-menu-item'][normalize-space(text())='Neurologa']"));
    JavascriptExecutor js = (JavascriptExecutor) driver;
    String output=(String) js.executeScript("return arguments[0].innerHTML;", element);
    System.out.println(output);
    

    Upvotes: 0

    Related Questions