package com.algocrafts.selenium; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.support.ui.FluentWait; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; import java.util.function.Supplier; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; public interface ExplicitWait<T extends SearchScope<T>> { /** * Save the screenshot if possible. */ void onTimeout(); /** * @param by selector * @return the element found by using the locator * @throws NoSuchElementException not found */ default Element until(Supplier<By> by) throws NoSuchElementException { return until(30, SECONDS, by); //<1> } /** * @param predicate predicate * @throws TimeoutException timeout */ default void until(Predicate<T> predicate) throws TimeoutException { until(30, SECONDS, predicate); } /** * @param duration timeout duration * @param timeUnit unit * @param by selector * @return the element found by using the locator * @throws NoSuchElementException not found */ default Element until(int duration, TimeUnit timeUnit, Supplier<By> by) throws NoSuchElementException { try { FluentWait<T> fluentWait = fluentWait(duration, timeUnit); return fluentWait.until( (T where) -> where.findElement(by.get()) //<2> ); } catch (TimeoutException e) { onTimeout(); throw new NoSuchElementException("Nothing found using " + by, e); } } /** * @param duration timeout duration * @param timeUnit unit * @param predicate predicate * @throws TimeoutException timeout */ default void until(int duration, TimeUnit timeUnit, Predicate<T> predicate) throws TimeoutException { try { FluentWait<T> fluentWait = fluentWait(duration, timeUnit); fluentWait.until( (T where) -> predicate.test(where) ); } catch (TimeoutException e) { onTimeout(); throw e; } } /** * @param duration timeout duration * @param timeUnit unit * @return the FluentWait instance */ @SuppressWarnings("unchecked") default FluentWait<T> fluentWait(int duration, TimeUnit timeUnit) { return new FluentWait<>((T) this) //<3> .withTimeout(duration, timeUnit) .pollingEvery(5, MILLISECONDS) .ignoring(Exception.class); } }