package ch.scaille.tcwriter.pilot.selenium;

import java.time.Duration;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.function.Function;
import java.util.function.Predicate;

import org.openqa.selenium.ElementNotInteractableException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.UnhandledAlertException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.WebDriverWait;

import ch.scaille.util.helpers.Poller;

public class SeleniumPoller extends Poller {

	private WebDriver webDriver;
	private TimeoutException timeoutException;

	public SeleniumPoller(WebDriver webDriver, Duration timeout, Duration firstDelay, DelayFunction delayFunction) {
		super(timeout, firstDelay, delayFunction);
		this.webDriver = webDriver;
	}

	public <T> T run(Function<Poller, T> polling, Predicate<T> isSuccess,
			Function<TimeoutException, T> timeoutHandler) {
		timeoutException = null;
		T result = run(polling, isSuccess);
		if (timeoutException != null) {
			return timeoutHandler.apply(timeoutException);
		}
		return result;
	}

	@Override
	public <T> T run(Function<Poller, T> polling, Predicate<T> isSuccess) {
		try {
			beforeRun();
			T result = pollWithSpecificDelay(polling, isSuccess, firstDelay);
			if (isSuccess.test(result)) {
				return result;
			}
			return pollWithSpecificDelay(polling, isSuccess, delayFunction.apply(this));
		} catch (TimeoutException e) {
			timeoutException = e;
			return null;
		}
	}

	private <T> T pollWithSpecificDelay(Function<Poller, T> polling, Predicate<T> isSuccess, Duration duration) {
		return new WebDriverWait(webDriver, timeTracker.remainingDuration()) //
				.pollingEvery(duration) //
				.ignoreAll(Arrays.asList(NoSuchElementException.class, StaleElementReferenceException.class,
						ElementNotInteractableException.class, UnhandledAlertException.class))
				.<T>until(d -> {
					T result = polling.apply(this);
					if (!isSuccess.test(result)) {
						return null;
					}
					return result;
				});

	}
}
@@ -204,16 +204,138 @@
 dicate;%0A
+import java.util.logging.Level;%0Aimport java.util.logging.Logger;%0A%0Aimport org.junit.platform.commons.logging.LoggerFactory;
 %0Aimport 
@@ -673,16 +673,58 @@
 .Poller;
+%0Aimport io.netty.handler.logging.LogLevel;
 %0A%0Apublic
@@ -763,16 +763,92 @@
 ller %7B%0A%0A
+%09private Logger LOGGER = Logger.getLogger(SeleniumPoller.class.getName());%0A%0A
 %09private
@@ -912,16 +912,44 @@
 ception;
+%0A%09private Object lastResult;
 %0A%0A%09publi
@@ -1356,22 +1356,104 @@
 null
+ && lastResult != null) %7B%0A%09%09%09return (T) lastResult;%0A%09%09%7D else if (timeoutException != null
 ) %7B%0A%09%09%09
-return 
 time
@@ -1856,24 +1856,73 @@
 eption e) %7B%0A
+%09%09%09LOGGER.log(Level.INFO, %22Polling timeout%22, e);%0A
 %09%09%09timeoutEx
@@ -2406,16 +2406,42 @@
 (this);%0A
+%09%09%09%09%09lastResult = result;%0A
 %09%09%09%09%09if 

Improve selenium test failure