How to use Fluent Wait Predicate and Function

6,813 views
Skip to first unread message

sunny sachdeva

unread,
Aug 22, 2013, 12:35:18 PM8/22/13
to webd...@googlegroups.com
Just out of curosity wanted to know how can we use Fluent Wait Predicate and Function

The little bit of googling gave me below code

 
    public void waitForWebElementFluently(){

        new FluentWait<WebElement>(countdown).
                withTimeout(10, TimeUnit.SECONDS).
                pollingEvery(100,TimeUnit.MILLISECONDS).
                until(new Function<WebElement, Boolean>() {
                    @Override
                    public Boolean apply(WebElement element) {
                        return element.getText().endsWith("04");
                    }
                }
                );
    }

i dont understand what does this endsWith means.
  public void waitForWebElementFluentlyPredicate(){

        new FluentWait<WebElement>(countdown).
                withTimeout(10, TimeUnit.SECONDS).
                pollingEvery(100,TimeUnit.MILLISECONDS).
                until(new Predicate<WebElement>() {
                    @Override
                    public boolean apply(WebElement element) {
                        return element.getText().endsWith("04");
                    }
                }
                );
    }

Also what is the difference between Predicate and Function over here.

sunny sachdeva

unread,
Aug 26, 2013, 4:40:01 AM8/26/13
to webd...@googlegroups.com
No one would like to comment on below ....

darrell

unread,
Aug 26, 2013, 7:44:52 AM8/26/13
to webd...@googlegroups.com
Rather than using Google, have you tried reading the API documentation for FluentWait? It can be found at http://selenium.googlecode.com/git/docs/api/java/index.html.

The example you give wait for 10 seconds, checking every 100 milliseconds until the WebElement getText() method returns a string which ends with "04". If it finds an element it returns the element. If after 10 seconds no such element exists then it will return NoSuchElementException.

I haven't used these. I'd have to read the API documentation more closely to understand the different between the Predicate and Function methods. In this instance they seem the same.

tangjin...@gmail.com

unread,
Aug 27, 2013, 11:26:18 PM8/27/13
to webd...@googlegroups.com
difference:
     Use function, if  apply method return true or false or timeout , then finish wait.
     Use Predicate , only timeout or return true,  then finish wait , 
     for example , timeout time :30s, element visible at 15s,  element.getText()   is   514,  
     then,   use function,  wait method end run at 15s, because,  element.getText().endsWith("04"); return false at 15s, then  method run over 
               use  Predicate, wait methon end run at 30s,  because,  element.getText().endsWith("04"); return false ,  but   Predicate  always waiting for   element.getText().endsWith("04"); return true;  
     because ,  

darrell

unread,
Aug 28, 2013, 8:40:30 PM8/28/13
to webd...@googlegroups.com
You can use either new Predicate<WebElement>() or new Function<WebElement, Boolean>(). The Predicate will return a boolean. The Function can return a boolean which will get promoted to a Boolean. They are, for the most part the same in this situation.

With a FluentWait you give it the element you want to pass to the apply() method. In this case the FluentWait<WebElement> will need a WebElement. So I can say that the countdown variable is a WebElement. The rest of the initialization is for 10 second, check every 100 milliseconds to see if the until Function/Predicate returns true. If the Function/Predicate returns true the FluentWait stops waiting. Otherwise it will wait for 10 seconds then throw an exception.

The Function has two parameters. The first is the input and the second is the return type of the apply() method. The Predicate takes one parameter which is the input. There is no second parameter because its apply() always returns boolean.

So every 100 millisecond, for a maximum of 10 seconds this code will check the WebElement countdown (element also refers to the same WebElement) to see if countdown.getText().endsWith("04") is true. If you want to break this out to be a little more obvious you could write:

    public boolean apply(WebElement element) {
        String text = element.getText();
        boolean flag = text.endsWith("04");
        return flag;
    }

Exact same thing but a lot more typing. You could also do things like:

    public void waitForButtonToBeVisible() {
        new FluentWait<WebDriver>(driver).
                withTimeout(3, TimeUnit.SECONDS).
                pollingEvery(50, TimeUnit.MILLISECONDS).
                ignoring(NoSuchElementException.class).
                until(new Predicate<WebDriver>() {
                    public boolean apply(WebDriver d) {
                        WebElement w = d.findElement(By.cssSelector("#editor1"));
                        return w.isDisplayed();
                    }
                }
    }

This will takes as input a WebDriver. It will try for 3 seconds, checking every 50 milliseconds to see if the WebElement is displayed. It will also ignore NoSuchElementException. So it might check for the element, it does not exist, the apply function ignores the NoSuchElementException. It keeps check every 50 milliseconds. At some point the element exists in the DOM but it is not visible. So the apply method returns false (rather than a NoSuchElementException). It keeps checking every 50 milliseconds so long as the timer is not at 3 seconds. If the element becomes visible within 3 seconds, the apply function returns true and the FluentWait stops checking. If the element never exists or it is never visible then the method will throw a TimeoutException.

Darrell


On Thursday, 22 August 2013 12:35:18 UTC-4, sunny sachdeva wrote:
Reply all
Reply to author
Forward
0 new messages