WebDriverWait.until(ExpectedConditions.elementToBeClickable(someAjaxMagic)) never returns

33,452

Solution 1

@snieke, try upgrading your selenium version to 2.28.0. I'm 99% sure that will work for you.

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-java</artifactId>
  <version>2.28.0</version>
</dependency>

Solution 2

Do you get a timeout exception, you are supposed to get it after 30 seconds. You can try:

try {
    wait.until(elementToBeClickable(By.partialLinkText("Zum Warenkorb")));
} catch (TimeoutException e) {
    // Do not stop the test, continue and see what happens
    LOG.info("Timed out", e);
}
driver.findElement(By.partialLinkText("Zum Warenkorb")).click();

it should continue after 30 seconds

EDIT:

Then try writing your own condition, here is what I have(you need to tweak it to suit your needs):

public class WebElementIsVisible implements ExpectedCondition<Boolean> {

    private WebElement element;
    private String elementId;

    public WebElementIsVisible(WebElement elementId) {
        this.element = elementId;
    }

    public WebElementIsVisible(String elementId) {
        this.elementId = elementId;
    }

    @Override
    public Boolean apply(WebDriver webDriver) {
        if (element != null) {
            return isElementVisible(element, webDriver);
        } else if (elementId != null) {
            return isElementIdVisible(elementId, webDriver);
        } else {
            throw new RuntimeException("Not supposed to reach here");
        }
    }

    private Boolean isElementIdVisible(String elementId, WebDriver webDriver) {
        try {
            webDriver.findElement(By.id(elementId));
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    private Boolean isElementVisible(WebElement element, WebDriver webDriver) {
        try {
            webDriver.findElement(By.id(element.getAttribute("id")));
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

}
Share:
33,452
snieke
Author by

snieke

Updated on December 16, 2020

Comments

  • snieke
    snieke over 3 years

    I have a problem with Selenium. In the following test, it should go to the website, take a product, add it to the cart and go to the cart. In between, it waits for some elements to appear.

    On my machine the test works fine up to adding the product to the cart. After this, a div is filled with ajax and the test should wait for an element in there. The element appears in the browser, but the test goes on waiting. Even the timeout seems not to be interesting enough to bother it.

    If I wait with wait.until(pause(2)); instead or set driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS); everything works fine but this can't be the correct solution.

    Any idea?

    My system:

    MacOS X 10.8.2 or Windows 7 (64 bit)

    Firefox 17.0.1

    Java 1.6, JUnit 4.10, selenium-api-2.25.0, selenium-support-2.25.0, selenium-firefox-driver-2.25.0, guava-12.0

    My test:

    import static org.openqa.selenium.support.ui.ExpectedConditions.elementToBeClickable;
    
    import javax.annotation.Nullable;
    
    import org.junit.Test;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.support.ui.WebDriverWait;
    
    import com.google.common.base.Function;
    
    public class TestSomeWebsite {
    
        @Test
        public void test() throws Exception {
            FirefoxDriver driver = new FirefoxDriver();
            WebDriverWait wait = new WebDriverWait(driver, 30);
    
            driver.get("http://www.obi.de");
    
            // take first product
            driver.findElement(By.cssSelector("p.product_desc > a")).click();
    
            // add to cart
            wait.until(elementToBeClickable(By.id("addtocart")));
            driver.findElement(By.id("addtocart")).submit();
    
            // go to cart
            /** everything fine by now **/
            wait.until(elementToBeClickable(By.partialLinkText("Zum Warenkorb")));
            /** we never come to this point :( **/
            driver.findElement(By.partialLinkText("Zum Warenkorb")).click();
        }
    
        private Function<WebDriver, Object> pause(final int time) {
            return new Function<WebDriver, Object>() {
                int count = 0;
    
                @Nullable
                public Object apply(@Nullable WebDriver input) {
                    count++;
                    return count >= time;
                }
            };
        }
    
    }