package org.richfaces.arquillian.browser; import java.lang.annotation.Annotation; import java.util.logging.Level; import java.util.logging.Logger; import org.jboss.arquillian.drone.spi.DroneInstanceEnhancer; import org.jboss.arquillian.drone.spi.InstanceOrCallableInstance; import org.jboss.arquillian.graphene.proxy.GrapheneProxy; import org.jboss.arquillian.graphene.proxy.GrapheneProxyInstance; import org.jboss.arquillian.graphene.proxy.Interceptor; import org.jboss.arquillian.graphene.proxy.InvocationContext; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriver; /** * Intercepts call of <code>WebDriver#get(url)</code> and tries to load the page up to 3 times, while catching TimeoutException. * Uses Graphene interceptors, so this enhancer needs to be called after GrapheneEnhancer. * * @author <a href="mailto:jstefek@redhat.com">Jiri Stefek</a> */ public class PageLoader implements DroneInstanceEnhancer<WebDriver> { private static final int DEFAULT_NUMBER_OF_REPEATS = 3; private static final String GET_METHOD_NAME = "get"; private static final Logger LOG = Logger.getLogger(PageLoader.class.getName()); private static final Interceptor interceptor = new PageLoadInterceptor(); @Override public boolean canEnhance(InstanceOrCallableInstance instance, Class<?> droneType, Class<? extends Annotation> qualifier) { return WebDriver.class.isAssignableFrom(droneType); } @Override public WebDriver deenhance(WebDriver instance, Class<? extends Annotation> qualifier) { if (GrapheneProxy.isProxyInstance(instance)) { GrapheneProxyInstance proxy = (GrapheneProxyInstance) instance; proxy.unregisterInterceptor(interceptor); } return instance; } @Override public WebDriver enhance(final WebDriver instance, Class<? extends Annotation> qualifier) { if (GrapheneProxy.isProxyInstance(instance)) { GrapheneProxyInstance proxy = (GrapheneProxyInstance) instance; proxy.registerInterceptor(interceptor); } return instance; } @Override public int getPrecedence() { return -101;// run after Graphene (-100) } private static final class PageLoadInterceptor implements Interceptor { @Override public int getPrecedence() { return 10;// run before other Graphene's interceptors (all have 0) } @Override public Object intercept(InvocationContext context) throws Throwable { if (context.getMethod().getName().equals(GET_METHOD_NAME)) { tryToLoadPage((WebDriver) context.getTarget(), String.valueOf(context.getArguments()[0])); return null;// skip any other interceptors } else { return context.invoke();// invoke method normally } } private void tryToLoadPage(WebDriver webDriver, String url) { for (int i = 1; i <= DEFAULT_NUMBER_OF_REPEATS; i++) { try { webDriver.get(url); return; } catch (TimeoutException e) { if (i == DEFAULT_NUMBER_OF_REPEATS) { throw e; } LOG.log(Level.INFO, "Page was not loaded within timeout. Trying to load it again, attempt #{0}", (i + 1)); } } } } }