package com.constellio.sdk.tests.selenium;
import static com.constellio.sdk.tests.SDKConstellioFactoriesInstanceProvider.DEFAULT_NAME;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.util.Date;
import java.util.Map;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxBinary;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import com.constellio.app.client.services.AdminServicesSession;
import com.constellio.app.start.ApplicationStarter;
import com.constellio.client.cmis.client.CmisSessionBuilder;
import com.constellio.model.conf.FoldersLocator;
import com.constellio.sdk.SDKPasswords;
import com.constellio.sdk.tests.ConstellioTestSession;
import com.constellio.sdk.tests.FactoriesTestFeatures;
import com.constellio.sdk.tests.SkipTestsRule;
import com.constellio.sdk.tests.ZeUltimateFirefoxDriver;
import com.constellio.sdk.tests.ZeUltimateFirefoxProfile;
import com.constellio.sdk.tests.selenium.adapters.constellio.ConstellioWebDriver;
public class SeleniumTestFeatures {
private static boolean applicationStarted = false;
private static ConstellioWebDriver openedWebDriver;
private boolean waitUntilICloseTheBrowsers = false;
private FactoriesTestFeatures factoriesTestFeatures;
SkipTestsRule skipTestsRule;
private Map<String, String> sdkProperties;
private int port = 8080;
private int portSSL = 8443;
public static void afterAllTests() {
if (applicationStarted) {
ApplicationStarter.stopApplication();
applicationStarted = false;
}
if (openedWebDriver != null) {
closeOpenedWebDriver();
}
}
private static void closeOpenedWebDriver() {
openedWebDriver.quit();
openedWebDriver = null;
}
public void afterTest(boolean failed) {
ApplicationStarter.resetServlets();
if (waitUntilICloseTheBrowsers) {
waitForWebDriversToClose();
} else if (openedWebDriver != null) {
if (failed) {
Dimension dimension = openedWebDriver.manage().window().getSize();
openedWebDriver.manage().window().setSize(new Dimension(dimension.getWidth(), 1800));
openedWebDriver.snapshot("failure");
}
closeOpenedWebDriver();
}
waitUntilICloseTheBrowsers = false;
}
public void beforeTest(Map<String, String> theSdkProperties, FactoriesTestFeatures factoriesTestFeatures,
SkipTestsRule skipTestsRule) {
this.sdkProperties = theSdkProperties;
this.factoriesTestFeatures = factoriesTestFeatures;
this.skipTestsRule = skipTestsRule;
if (sdkProperties.containsKey("port")) {
try {
port = Integer.valueOf(sdkProperties.get("port"));
} catch (Exception e) {
port = 8080;
}
}
}
public CmisSessionBuilder newCmisSessionBuilder() {
disableAllServices();
System.setProperty("cmisEnabled", "true");
if (!applicationStarted) {
startApplication();
}
String url = "http://localhost:" + port + "/constellio/";
return CmisSessionBuilder.forAppUrl(url);
}
public AdminServicesSession newRestClient(String serviceKey, String username, String password) {
disableAllServices();
System.setProperty("driverEnabled", "true");
if (!applicationStarted) {
startApplication();
}
String url = "http://localhost:" + port + "/constellio/rest";
return AdminServicesSession.connect(url, serviceKey, username, password);
}
public WebTarget newWebTarget() {
return newWebTarget("/rest");
}
public WebTarget newWebTarget(String path) {
if (!path.isEmpty() && !path.startsWith("/")) {
path = "/" + path;
}
disableAllServices();
System.setProperty("driverEnabled", "true");
if (!applicationStarted) {
startApplication();
}
String url = "http://localhost:" + port + "/constellio/rest" + path;
javax.ws.rs.client.Client client = ClientBuilder.newClient();
return client.register(JacksonFeature.class).target(url);
}
public SolrClient newSearchClient() {
disableAllServices();
if (!applicationStarted) {
startApplication();
}
String url = "http://localhost:" + port + "/constellio";
SolrClient solrServer = new HttpSolrClient(url, null, new XMLResponseParser());
return solrServer;
}
public ConstellioWebDriver newWebDriver(boolean preferFirefox) {
return newWebDriver(preferFirefox, false);
}
public ConstellioWebDriver newWebDriver(boolean preferFirefox, boolean useSSL) {
disableAllServices();
if (!applicationStarted) {
startApplication();
}
String url;
if (useSSL) {
url = "https://localhost:" + portSSL + "/constellio";
} else {
url = "http://localhost:" + port + "/constellio";
}
String phantomJSBinaryDir = sdkProperties.get("phantomJSBinary");
String firefoxBinaryDir = sdkProperties.get("firefoxBinary");
String currentPageLoadTime;
if (openedWebDriver == null) {
WebDriver webDriver;
if (firefoxBinaryDir == null && phantomJSBinaryDir == null) {
throw new RuntimeException(
"You need to configure 'phantomJSBinary' or 'firefoxBinary' properties in sdk.properties file");
} else if (phantomJSBinaryDir == null || (firefoxBinaryDir != null && preferFirefox)) {
webDriver = newFirefoxWebDriver(firefoxBinaryDir);
} else {
webDriver = newPhantomJSWebDriver(phantomJSBinaryDir);
}
FoldersLocator foldersLocator = factoriesTestFeatures.getFoldersLocator(DEFAULT_NAME);
openedWebDriver = new ConstellioWebDriver(webDriver, url, foldersLocator, skipTestsRule);
currentPageLoadTime = "";
} else {
currentPageLoadTime = openedWebDriver.getPageLoadTimeAsString(2000);
openedWebDriver.manage().deleteAllCookies();
}
boolean customWindowPosition = ConstellioTestSession.get().isDeveloperTest();
if (customWindowPosition) {
String positionXConfig = sdkProperties.get("window.position.x");
String positionYConfig = sdkProperties.get("window.position.y");
String widthConfig = sdkProperties.get("window.width");
String heightConfig = sdkProperties.get("window.height");
if (StringUtils.isNotBlank(positionXConfig) && StringUtils.isNotBlank(positionYConfig)) {
int positionX = Integer.valueOf(positionXConfig);
int positionY = Integer.valueOf(positionYConfig);
openedWebDriver.manage().window().setPosition(new Point(positionX, positionY));
}
if (StringUtils.isNotBlank(widthConfig) && StringUtils.isNotBlank(heightConfig)) {
int width = Integer.valueOf(widthConfig);
int height = Integer.valueOf(heightConfig);
openedWebDriver.manage().window().setSize(new Dimension(width, height));
} else {
openedWebDriver.manage().window().setSize(new Dimension(1200, 1024));
}
} else {
openedWebDriver.manage().window().setSize(new Dimension(1200, 1024));
}
boolean ready = false;
Exception exception = null;
for (int i = 0; i < 10 && !ready; i++) {
try {
openedWebDriver.gotoConstellio();
openedWebDriver.waitForPageReload(20, currentPageLoadTime);
ready = true;
} catch (Exception e) {
exception = e;
}
}
if (!ready) {
throw new RuntimeException(exception);
}
return openedWebDriver;
}
public ConstellioWebDriver newWebDriverSSL(boolean preferFirefox) {
disableAllServices();
if (!applicationStarted) {
startApplication();
}
String url = "http://localhost:" + portSSL + "/constellio";
String phantomJSBinaryDir = sdkProperties.get("phantomJSBinary");
String firefoxBinaryDir = sdkProperties.get("firefoxBinary");
String currentPageLoadTime;
if (openedWebDriver == null) {
WebDriver webDriver;
if (firefoxBinaryDir == null && phantomJSBinaryDir == null) {
throw new RuntimeException(
"You need to configure 'phantomJSBinary' or 'firefoxBinary' properties in sdk.properties file");
} else if (phantomJSBinaryDir == null || (firefoxBinaryDir != null && preferFirefox)) {
webDriver = newFirefoxWebDriver(firefoxBinaryDir);
} else {
webDriver = newPhantomJSWebDriver(phantomJSBinaryDir);
}
FoldersLocator foldersLocator = factoriesTestFeatures.getFoldersLocator(DEFAULT_NAME);
openedWebDriver = new ConstellioWebDriver(webDriver, url, foldersLocator, skipTestsRule);
currentPageLoadTime = "";
} else {
currentPageLoadTime = openedWebDriver.getPageLoadTimeAsString(2000);
openedWebDriver.manage().deleteAllCookies();
}
openedWebDriver.manage().window().setSize(new Dimension(1200, 1024));
boolean ready = false;
Exception exception = null;
for (int i = 0; i < 10 && !ready; i++) {
try {
openedWebDriver.gotoConstellio();
openedWebDriver.waitForPageReload(20, currentPageLoadTime);
ready = true;
} catch (Exception e) {
exception = e;
}
}
if (!ready) {
throw new RuntimeException(exception);
}
return openedWebDriver;
}
private WebDriver newPhantomJSWebDriver(String phantomJSBinaryDir) {
System.setProperty("phantomjs.binary.path", phantomJSBinaryDir);
try {
return new PhantomJSDriver(DesiredCapabilities.phantomjs());
} catch (Exception e) {
throw new RuntimeException("Could not start PhantomJS in directory '" + phantomJSBinaryDir + "'", e);
}
}
private WebDriver newFirefoxWebDriver(String firefoxBinaryDir) {
WebDriver webDriver;
if (firefoxBinaryDir.equals("detect")) {
webDriver = newDefaultFirefoxWebDriver();
} else {
webDriver = newFirefoxWebDriverWithSpecificBinDirectory(firefoxBinaryDir);
}
return webDriver;
}
private ZeUltimateFirefoxDriver newDefaultFirefoxWebDriver() {
try {
return new ZeUltimateFirefoxDriver();
} catch (Exception e) {
throw new RuntimeException("Could not detect or start Firefox", e);
}
}
private ZeUltimateFirefoxDriver newFirefoxWebDriverWithSpecificBinDirectory(String firefoxBinaryDir) {
try {
FirefoxBinary firefoxBinary = new FirefoxBinary(new File(firefoxBinaryDir));
ZeUltimateFirefoxProfile firefoxSchema = new ZeUltimateFirefoxProfile();
return new ZeUltimateFirefoxDriver(firefoxBinary, firefoxSchema);
} catch (Exception e) {
throw new RuntimeException("Could not start Firefox in directory '" + firefoxBinaryDir + "'", e);
}
}
public void waitUntilICloseTheBrowsers() {
waitUntilICloseTheBrowsers = true;
}
public String startApplication() {
File webContent = new FoldersLocator().getAppProjectWebContent();
long time = new Date().getTime();
assertThat(webContent).exists().isDirectory();
File webInf = new File(webContent, "WEB-INF");
assertThat(webInf).exists().isDirectory();
assertThat(new File(webInf, "web.xml")).exists();
assertThat(new File(webInf, "sun-jaxws.xml")).exists();
File cmis11 = new File(webInf, "cmis11");
assertThat(cmis11).exists().isDirectory();
assertThat(cmis11.listFiles()).isNotEmpty();
ApplicationStarter.startApplication(false, webContent, port);
applicationStarted = true;
System.out.println("Application started in " + (new Date().getTime() - time) + "ms");
return "http://localhost:" + port + "/constellio/";
}
public String startApplicationWithSSL(boolean keepAlive) {
File webContent = new FoldersLocator().getAppProjectWebContent();
long time = new Date().getTime();
assertThat(webContent).exists().isDirectory();
File webInf = new File(webContent, "WEB-INF");
assertThat(webInf).exists().isDirectory();
assertThat(new File(webInf, "web.xml")).exists();
assertThat(new File(webInf, "sun-jaxws.xml")).exists();
File cmis11 = new File(webInf, "cmis11");
assertThat(cmis11).exists().isDirectory();
assertThat(cmis11.listFiles()).isNotEmpty();
ApplicationStarter.startApplication(keepAlive, webContent, portSSL, SDKPasswords.sslKeystorePassword());
applicationStarted = true;
System.out.println("Application started in " + (new Date().getTime() - time) + "ms");
return "http://localhost:" + portSSL + "/constellio/";
}
public void stopApplication() {
ApplicationStarter.stopApplication();
}
private void waitForWebDriversToClose() {
try {
while (true) {
openedWebDriver.getCurrentUrl();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
} catch (RuntimeException e) {
return;
// Web driver closed
}
}
public void disableAllServices() {
System.setProperty("driverEnabled", "false");
System.setProperty("cmisEnabled", "false");
System.setProperty("benchmarkServiceEnabled", "false");
}
public ConstellioWebDriver getLastWebDriver() {
return openedWebDriver;
}
}