/*******************************************************************************
* Copyright (c) 2010-2014 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.skalli.selenium.utils;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import org.eclipse.skalli.selenium.pageobjects.concrete.LoginFailedPage;
import org.eclipse.skalli.selenium.pageobjects.concrete.LoginPage;
import org.eclipse.skalli.selenium.pageobjects.concrete.MainPage;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.support.PageFactory;
import com.thoughtworks.selenium.SeleniumException;
/**
* The DriverProvider can be used to get a {@link org.openqa.selenium.WebDriver} instance which
* will be instantiated, started, stopped when the program terminates and which will {@link org.openqa.selenium.WebDriver#get(String)}
* the base url ({@link #getHTTPBaseUrl()}).
* <br/>
* The DriverProvider provides a method to {@link #login(WebDriver)} on the page and a method to be able to navigate to the
* base url ({@link #navigateToBaseUrl(WebDriver)}).
*/
public class DriverProvider {
/**
* The host system property "tomcat.host" or "localhost" by default
*/
private static final String TOMCAT_HOST = System.getProperty("tomcat.host", "localhost");
/**
* The port system property "tomcat.http.port" or "8080" by default
*/
private static final int TOMCAT_HTTP_PORT = Integer.parseInt(System.getProperty("tomcat.http.port", "8080"));
/**
* The folder containing the browser plugins
*/
private static final File BROWSER_PLUGINS_FOLDER = new File("browser_plugins");
/**
* Directory where test content can be copied from
*/
private static final File TEST_CONTENT_DIR = new File("testdata");
/**
* Storage directory for test content
*/
private static final File STORAGE_DIR = new File("workdir/storage");
/**
* The driver
*/
private static WebDriver driver;
/**
* The shutdown hook
*/
private static Thread shutdownHook = new Thread() {
@Override
public void run() {
stopDriver();
}
};
/**
* Returns the {@link org.openqa.selenium.WebDriver} instance used for the tests.
* The driver navigates to the URL returned by {@link #getHTTPBaseUrl()}
* @return The {@link org.openqa.selenium.WebDriver} instance used for the tests.
*/
public static WebDriver getDriver() {
if (driver == null) {
startDriver();
}
return driver;
}
/**
* Restarts the driver (means it stops the driver and then starts it again).
* @return The driver to be used now
*/
public static WebDriver restartDriver() {
stopDriver();
startDriver();
return driver;
}
/**
* Deletes all cookies so the login page can be displayed again
*/
public static void goToLoginPage() {
driver.manage().deleteAllCookies();
navigateToBaseUrl(driver);
//waits for the login page to be displayed
LoginPage login = PageFactory.initElements(driver, LoginPage.class);
login.isDisplayedWithExplicitWait();
}
/**
* Starts the driver, adds a shutdown hook to stop the driver and navigates to {@link #getHTTPBaseUrl()}
*/
private static void startDriver() {
FirefoxProfile profile = new FirefoxProfile();
//load the browser plugins
if (BROWSER_PLUGINS_FOLDER.exists()) {
File[] plugins = BROWSER_PLUGINS_FOLDER.listFiles();
for (int i = 0; i < plugins.length; i++) {
File plugin = plugins[i];
String name = plugin.getName();
if (!name.toLowerCase().contains(".xpi")) {
System.err.println("\"" + name + "\" is not a plugin -> remove from " + BROWSER_PLUGINS_FOLDER);
continue;
}
//pluginName = "firebug-" + FIREBUG_VERSION + ".xpi"
//pluginName = "firepath-" + FIREPATH_VERSION + "-fx.xpi"
//set up the plugin if needed
if (name.toLowerCase().contains("firebug")) {
//pluginName = "firebug-" + FIREBUG_VERSION + ".xpi"
String version = name.substring("firebug-".length());
version = version.substring(0, version.length() - ".xpi".length());
//avoids that the first run page is shown
profile.setPreference("extensions.firebug.currentVersion", version);
}
//add the plugin
try {
profile.addExtension(plugin);
} catch (IOException e) {
System.err.println("could not add extension \"" + name + "\" to the profile\n" + e);
e.printStackTrace();
}
}
}
driver = new FirefoxDriver(profile);
registerShutdownHook();
driver.get(getHTTPBaseUrl());
copyTestContent();
}
private static void copyTestContent() {
try {
FileUtils.copyDirectory(TEST_CONTENT_DIR, STORAGE_DIR);
} catch (IOException e) {
throw new SeleniumException("failed to copy test content", e);
}
}
private static void removeTestContent() {
try {
FileUtils.deleteDirectory(STORAGE_DIR);
} catch (IOException e) {
throw new SeleniumException("failed to delete test content", e);
}
}
/**
* Stops the driver
*/
private static void stopDriver() {
driver.quit();
driver = null;
removeTestContent();
}
/**
* Registers a shutdown hook via {@link Runtime#addShutdownHook(Thread)}
*/
private static void registerShutdownHook() {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
/**
* Returns the http base URL
* @return the http base URL
*/
private static String getHTTPBaseUrl() {
return "http://" + TOMCAT_HOST + ":" + TOMCAT_HTTP_PORT;
}
/**
* Navigates to the base url ({@link #getHTTPBaseUrl()})
* @param driver The driver
*/
public static void navigateToBaseUrl(WebDriver driver) {
driver.navigate().to(getHTTPBaseUrl());
}
/**
* Navigates to "{@link #getHTTPBaseUrl()} + {@code subUrl}"
* @param driver The driver
* @param subUrl The sub url
*/
public static void navigateToSubUrl(WebDriver driver, String subUrl) {
driver.navigate().to(getHTTPBaseUrl() + subUrl);
}
/**
* Try to login with the given user name and password
* @param driver The {@link org.openqa.selenium.WebDriver}
* @param username The user name
* @param password The password
* @return {@code true} if the login was possible, {@code false} otherwise
*/
public static boolean login(WebDriver driver, String username, String password) {
try {
LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class);
LoginFailedPage loginFailedPage = PageFactory.initElements(driver, LoginFailedPage.class);
MainPage mainPage = PageFactory.initElements(driver, MainPage.class);
driver.manage().timeouts().implicitlyWait(500, TimeUnit.MILLISECONDS);
while (loginPage.isDisplayed()) {
loginPage.sendKeysToUserNameAndPasswordFieldAndSubmit(username, password);
driver.manage().timeouts().implicitlyWait(500, TimeUnit.MILLISECONDS);
//avoiding that the driver is positioned at getHTTPBaseUrl() + "/favicon.ico"
//maybe a bug!?
try {
if (!loginFailedPage.isDisplayed() && !mainPage.isDisplayed()) {
navigateToBaseUrl(driver);
}
} catch (Exception e) {
}
//if the login page is displayed the login was successful
try {
if (mainPage.isDisplayed()) {
return true;
}
} catch (Exception e) {
}
}
} catch (NoSuchElementException e) {
return false;
}
//should never be reached
return true;
}
/**
* Try to login with user name = "admin" and password = "admin"
* @param driver The {@link org.openqa.selenium.WebDriver}
* @return {@code true} if the login was possible, {@code false} otherwise
*/
public static boolean login(WebDriver driver) {
return login(driver, "admin", "admin");
}
/**
* Returns whether the driver is located on the login page or not
* @param driver The driver
* @return {@code true} if the driver is on the login page {@code false} otherwise
*/
public static boolean isOnLoginPage(WebDriver driver) {
try {
LoginPage login = PageFactory.initElements(driver, LoginPage.class);
driver.manage().timeouts().implicitlyWait(500, TimeUnit.MILLISECONDS);
login.isDisplayed();
} catch (NoSuchElementException e) {
return false;
}
return true;
}
}