Can not understand the implementation of until() m

2019-05-02 09:33发布

The until() method in org.openqa.selenium.support.ui.FluentWait is overloaded for Predicate<T> and Function<? super T, V> interfaces as parameters.

It should take as argument one of the following (which implement the apply() method):

  • Anonymous class
  • Lambda expression
  • Method reference

Any lambda that I define as argument for this method throws following error:

The method until(Predicate) is ambiguous for the type WebDriverWait

My Lambda:

x -> x.findElement(byLocator).isDisplayed()

I assume this will be the case for any lambda, as apply() for either Function or Predicate can be implemented by use of these lambda.

So my question is what is the use of the until method which takes Predicate as parameter?

Updated: Removed the first part of question which was answered by @drkthng.

4条回答
对你真心纯属浪费
2楼-- · 2019-05-02 09:39

Below functional interface implementation should resolved issue:

FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
    wait.pollingEvery(500, TimeUnit.MILLISECONDS);
    wait.withTimeout(5, TimeUnit.MINUTES);
    wait.ignoring(NoSuchElementException.class);
    wait.until((WebDriver arg0) ->{
    WebElement element = arg0.findElement(By.id("colorVar"));
    String color = element.getAttribute("style");
    System.out.println("The color if the button is " + color);
    if(color.equals("color: red;"))
    {
        return true;
    }
    return false;
    }); 
查看更多
forever°为你锁心
3楼-- · 2019-05-02 09:46

Answering your first question:

Have a look at the Selenium API docs for ExpectedConditon.

I quote:

public interface ExpectedCondition<T>
extends com.google.common.base.Function<WebDriver,T>

You see, that ExpectedCondition inherited from google's Function interface, thus you can use it as an argument for the until() method.

As for your second question:

I don't think you can hand over a lambda just like that. Until method is waiting for a Predicate or Function (as you correctly mentioned).

Regarding the differences between Predicates and lambdas, have a look for example here

So you can try something like this instead, still using your lambda-expressions:

Predicate<WebDriver> myPredicate = x ->x.findElement(By.id("id")).isDisplayed();

WebDriverWait wait = (WebDriverWait)new WebDriverWait(driver, 10);
wait.until(myPredicate);
查看更多
Luminary・发光体
4楼-- · 2019-05-02 09:56

As you said the method until is overloaded and the parameters expected are Predicate<T> and Function<? super T, V>.

Your lambda expression match both signatures, so the call to the method is ambiguous, to solve the ambiguity, there are several options:

Cast the lambda expression to the desired type:

until((Predicate<WebDriver>) x -> x.findElement(byLocator).isDisplayed());

If you create a variable for the lambda expression, the cast is not needed:

Predicate<WebDriver> p = x.findElement(byLocator).isDisplayed();
until(p);

If you have a method with this functionality, you can use a method reference:

boolean testMethod(WebDriver x) {
    return x.findElement(byLocator).isDisplayed();
} 

until(MyClass::testMethod);
查看更多
时光不老,我们不散
5楼-- · 2019-05-02 09:56

You are getting the error as your lambda expression match both the predicate and function.

Consider upgrading the selenium to v3.2.0 -> in which the FluentWait.until(Predicate<?>) method is deprecated. And that should make lambdas work properly with Wait instances now.

查看更多
登录 后发表回答