package com.gfk.senbot.framework.context; import java.awt.AWTException; import java.awt.Robot; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.openqa.selenium.Platform; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.FindBys; import org.openqa.selenium.support.PageFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.gfk.senbot.framework.cucumber.stepdefinitions.ScenarioGlobals; /** * Manager of all selenium related configuration and runtime variables. * The selenium driver is initiated here. * Also the settings for running on the grid or on the local machine. * * @author joostschouten * */ public class SeleniumManager { private static Logger log = LoggerFactory.getLogger(SeleniumManager.class); private String defaultDomain = null; private URL seleniumHub = null; private ArrayList<TestEnvironment> seleniumTestEnvironments = new ArrayList<TestEnvironment>(); private final Integer defaultWindowWidth; private final Integer defaultWindowHeight; private int timeout; private Integer implicitTimeout; private Map<Thread, TestEnvironment> associatedEnvironment = new HashMap<Thread, TestEnvironment>(); private WebDriverCreationHook webDriverCreationHook; public SeleniumManager( String defaultDomain, String seleniumHubIP, String target, int defaultWindowWidth, int defaultWindowHeight, int aTimeout) throws IOException, AWTException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { this(defaultDomain, seleniumHubIP, target, defaultWindowWidth, defaultWindowWidth, aTimeout, null, null); try { //move the mouse to 0,50 so that it won't interfere with IE native events. 50 to avoid trigger of hotcorners Robot robot = new Robot(); robot.mouseMove(0, 50); } catch (AWTException awte) { //thrown when the process is running headless, just continue without moving the cursor } } /** * {@link SeleniumManager} constructor managed by spring * * @param defaultDomain domain the whole selenium related SenBot will work from * @param seleniumHubIP if running on a grid this is the hub ip to be used * @param target The target environements to run the selenium tests on * @param defaultWindowWidth browser window width to start the browser with * @param defaultWindowHeight browser window height to start the browser with * @param aTimeout implicit timeout to be used by selenium when performing a dom lookup or page refresh * @throws IOException */ public SeleniumManager( String defaultDomain, String seleniumHubIP, String target, int defaultWindowWidth, int defaultWindowHeight, int aTimeout, String implicitTimeout, String webdriverCreationHookClassName) throws IOException, ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException { if(!StringUtils.isBlank(webdriverCreationHookClassName)) { Constructor<?> constructor = Class.forName(webdriverCreationHookClassName).getConstructor(); webDriverCreationHook = (WebDriverCreationHook) constructor.newInstance(); } if(defaultDomain != null) { if(defaultDomain.toLowerCase().startsWith("http")) { this.defaultDomain = defaultDomain; } else { this.defaultDomain = "http://" + defaultDomain; } } this.defaultWindowWidth = defaultWindowWidth; this.defaultWindowHeight = defaultWindowHeight; this.timeout = aTimeout; if (!StringUtils.isBlank(implicitTimeout)) { this.implicitTimeout = Integer.parseInt(implicitTimeout); } this.seleniumHub = (StringUtils.isBlank(seleniumHubIP)) ? null : new URL(seleniumHubIP); if (StringUtils.isBlank(target)) { throw new IllegalArgumentException("The selenium target environment property cannot be blank. Refer to senbot-runner.properties"); } else { for (String ii : target.split(";")) { String[] parts = ii.split(","); String browserVersion = parts.length > 1 ? parts[1].trim() : "ANY"; Platform platform = Platform.valueOf(parts.length > 2 ? parts[2].trim() : "ANY"); String locale = parts.length > 3 ? parts[3].trim() : null; TestEnvironment testEnvironment = new TestEnvironment(parts[0].trim(), browserVersion, platform, locale); seleniumTestEnvironments.add(testEnvironment); } } } /** * Check {@link PageFactory} for how these Objects are instantiated using the {@link FindBy} and {@link FindBys} annotations. * Senbot will cache your objects in the Scenario globals so that they only get initialized once * * @param T * @return instanciated T */ public <T> T getViewRepresentation(Class<T> T) { return getViewRepresentation(T, false); } /** * Check {@link PageFactory} for how these Objects are instantiated using the {@link FindBy} and {@link FindBys} annotations. * Senbot will cache your objects in the Scenario globals so that they only get initialized once * * @param T * @param forceRefresh if true we will always reinstantiate * @return instanciated T */ public <T> T getViewRepresentation(Class<T> T, boolean forceRefresh) { ScenarioGlobals currentScenarioGlobals = SenBotContext.getSenBotContext().getCucumberManager().getCurrentScenarioGlobals(); T foundView = currentScenarioGlobals == null ? null : (T) currentScenarioGlobals.getAttribute(T.getName()); if(foundView == null || forceRefresh) { foundView = PageFactory.initElements(getAssociatedTestEnvironment().getWebDriver(), T); if(currentScenarioGlobals != null) { currentScenarioGlobals.setAttribute(T.getName(), foundView); } } return foundView; } /** * Cleaning up */ protected synchronized void cleanUp() { for (TestEnvironment env : seleniumTestEnvironments) { env.cleanupAllDrivers(); } seleniumTestEnvironments.clear(); } /** * @return the deault domain */ public String getDefaultDomain() { return defaultDomain; } /** * @return The URL of the Selenium Hub */ public URL getSeleniumHub() { return seleniumHub; } /** * @return List of all test environments managed by the SeleniumManager */ public List<TestEnvironment> getSeleniumTestEnvironments() { return seleniumTestEnvironments; } /** * * Associates Thread with TestEnvironment * * @param environment {@link TestEnvironment} to associate with the current {@link Thread} * @throws Exception */ public void associateTestEnvironment(TestEnvironment aTestEnvironment) throws Exception { log.debug("Associate TestEnvironment: " + aTestEnvironment.toPrettyString() + " with thread: " + Thread.currentThread().toString()); associatedEnvironment.put(Thread.currentThread(), aTestEnvironment); } /** * Deletes association of Thread with TestEnvironment * * @return {@link TestEnvironment} * * @throws InterruptedException */ public TestEnvironment deAssociateTestEnvironment() throws InterruptedException { Thread currentThread = Thread.currentThread(); TestEnvironment removed = associatedEnvironment.remove(currentThread); log.debug("Deassociated TestEnvironment: " + removed.toPrettyString() + " from thread: " + currentThread.toString()); return removed; } /** * @return {@link TestEnvironment} associated with the current {@link Thread} */ public TestEnvironment getAssociatedTestEnvironment() { return associatedEnvironment.get(Thread.currentThread()); } /** * @return Timeout in [s] */ public int getTimeout() { return timeout; } /** * @return defaultWindowWidth in [pixel] */ public int getDefaultWindowWidth() { return defaultWindowWidth; } /** * @return defaultWindowHeight in [pixel] */ public int getDefaultWindowHeight() { return defaultWindowHeight; } public Integer getImplicitTimeout() { return implicitTimeout; } public WebDriverCreationHook getWebDriverCreationHook() { return webDriverCreationHook; } }