62

I'm trying to make Selenium wait for an element that is dynamically added to the DOM after page load. I tried this:

fluentWait.until(ExpectedConditions.presenceOfElement(By.id("elementId"));

In case it helps, here is fluentWait:

FluentWait fluentWait = new FluentWait<>(webDriver) {
    .withTimeout(30, TimeUnit.SECONDS)
    .pollingEvery(200, TimeUnit.MILLISECONDS);
}

But it throws a NoSuchElementException. It looks like presenceOfElement expects the element to be there, so this is flawed. This must be bread and butter to Selenium, and I don't want to reinvent the wheel... Is there an alternative, ideally without rolling my own Predicate?

Steve Chambers
  • 37,270
  • 24
  • 156
  • 208

5 Answers5

81

You need to call ignoring with an exception to ignore while the WebDriver will wait.

FluentWait<WebDriver> fluentWait = new FluentWait<>(driver)
        .withTimeout(30, TimeUnit.SECONDS)
        .pollingEvery(200, TimeUnit.MILLISECONDS)
        .ignoring(NoSuchElementException.class);

See the documentation of FluentWait for more information. But beware that this condition is already implemented in ExpectedConditions, so you should use:

WebElement element = (new WebDriverWait(driver, 10))
   .until(ExpectedConditions.elementToBeClickable(By.id("someid")));

*Fewer versions of Selenium:

withTimeout(long, TimeUnit) has become withTimeout(Duration)
pollingEvery(long, TimeUnit) has become pollingEvery(Duration)

So the code will look as such:

FluentWait<WebDriver> fluentWait = new FluentWait<>(driver)
        .withTimeout(Duration.ofSeconds(30)
        .pollingEvery(Duration.ofMillis(200)
        .ignoring(NoSuchElementException.class);

A basic tutorial for waiting can be found here.

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
Petr Mensik
  • 26,874
  • 17
  • 90
  • 115
  • either it should be or it should be <> if you are using java 8 would give you compilation error. – Shek May 05 '17 at 03:44
  • 1
    Its NOT implemented in ExpectedCondition....its in WebDriverWait. public WebDriverWait(WebDriver driver, Clock clock, Sleeper sleeper, long timeOutInSeconds, long sleepTimeOut) { super(driver, clock, sleeper); this.withTimeout(timeOutInSeconds, TimeUnit.SECONDS); this.pollingEvery(sleepTimeOut, TimeUnit.MILLISECONDS); this.ignoring(NotFoundException.class); this.driver = driver; } – Sugat Mankar Jun 17 '17 at 03:57
16

Use:

WebDriverWait wait = new WebDriverWait(driver, 5)
wait.until(ExpectedConditions.visibilityOf(element));

You can use this as some time before loading the whole page, the code gets executed and throws an error. The time is in seconds.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bhupendra
  • 191
  • 1
  • 6
3

Let me recommend you using Selenide library. It allows writing much more concise and readable tests. It can wait for presence of elements with much shorter syntax:

$("#elementId").shouldBe(visible);

Here is a sample project for testing Google search: https://github.com/selenide-examples/google

Andrei Solntsev
  • 480
  • 2
  • 8
0

FluentWait throws a NoSuchElementException is case of the confusion

org.openqa.selenium.NoSuchElementException;     

with

java.util.NoSuchElementException

in

.ignoring(NoSuchElementException.class)
palandlom
  • 529
  • 6
  • 17
-1
public WebElement fluientWaitforElement(WebElement element, int timoutSec, int pollingSec) {

    FluentWait<WebDriver> fWait = new FluentWait<WebDriver>(driver).withTimeout(timoutSec, TimeUnit.SECONDS)
        .pollingEvery(pollingSec, TimeUnit.SECONDS)
        .ignoring(NoSuchElementException.class, TimeoutException.class).ignoring(StaleElementReferenceException.class);

    for (int i = 0; i < 2; i++) {
        try {
            //fWait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//*[@id='reportmanager-wrapper']/div[1]/div[2]/ul/li/span[3]/i[@data-original--title='We are processing through trillions of data events, this insight may take more than 15 minutes to complete.']")));
        fWait.until(ExpectedConditions.visibilityOf(element));
        fWait.until(ExpectedConditions.elementToBeClickable(element));
        } catch (Exception e) {

        System.out.println("Element Not found trying again - " + element.toString().substring(70));
        e.printStackTrace();

        }
    }

    return element;

    }
Roman Marusyk
  • 23,328
  • 24
  • 73
  • 116
Ashwini
  • 119
  • 2
  • 9