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;
}
}