/*
* Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) 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:
* bstefanescu
*/
package org.eclipse.ecr.testlib.runner.web;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.ecr.testlib.runner.FeaturesRunner;
import org.openqa.selenium.By;
import org.openqa.selenium.NotFoundException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import com.google.inject.Inject;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*
*/
public abstract class WebPage {
/**
* Can be used by tests as default timeouts. This way you can change these
* values to change all the timeout in the tests. DEFAULT_TIMEOUT is used
* for regular timeouts (loading an ajax page an ajax dialog etc.) while
* BIG_TIMEOUT should be used for pages that are slower (like the home of a
* GWT application)
*/
public static int DEFAULT_TIMEOUT = 5;
public static int BIG_TIMEOUT = 15;
private static final Map<Class<?>, WebPage> pages = new HashMap<Class<?>, WebPage>();
@Inject
protected Configuration config;
@Inject
protected WebDriver driver;
@Inject
protected FeaturesRunner runner;
/**
* Should be overridden by dynamic page (using ajax) to wait until the page
* is completely loaded By default nothing is done (page is assumed to be
* loaded)
*
* @return the page itself
*/
public WebPage ensureLoaded() {
return this; // do nothing by default
}
public Configuration getConfiguration() {
return config;
}
public WebDriver getDriver() {
return driver;
}
public FeaturesRunner getRunner() {
return runner;
}
public void home() {
driver.get(config.home);
}
public void to(String path) {
if (path.contains("://")) {
driver.get(path);
} else {
try {
URL url = new URL(new URL(config.home), path);
driver.navigate().to(url);
} catch (MalformedURLException e) {
throw new WebDriverException(e);
}
}
}
public boolean hasElement(final By by) {
try {
driver.findElement(by);
return true;
} catch (WebDriverException e) {
return false;
}
}
public boolean hasElement(final By by, int timeoutInSeconds) {
try {
findElement(by, timeoutInSeconds);
return true;
} catch (WebDriverException e) {
return false;
}
}
public WebElement findElement(final By by) {
return driver.findElement(by);
}
public List<WebElement> findElements(final By by) {
return driver.findElements(by);
}
public WebElement findElement(final By by, int timeOutInSeconds) {
return waitUntilElementFound(by, timeOutInSeconds);
}
public WebElement waitUntilElementFound(final By by, int timeOutInSeconds) {
try {
return findElement(by); // try once first
} catch (NotFoundException e) {
return new WebDriverWait(driver, timeOutInSeconds).until(new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver arg0) {
return driver.findElement(by);
}
});
}
}
public void waitUntilElementNotFound(final By by, int timeOutInSeconds) {
try {
findElement(by); // try once first
new WebDriverWait(driver, timeOutInSeconds).until(new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver arg0) {
try {
driver.findElement(by);
return Boolean.FALSE;
} catch (NotFoundException e) {
return Boolean.TRUE;
}
}
});
} catch (NotFoundException e) {
}
}
@SuppressWarnings("unchecked")
public <T extends WebPage> T getPage(Class<T> type) {
T page = (T) pages.get(type);
if (page == null) {
synchronized (pages) {
page = (T) pages.get(type);
if (page != null) {
return page;
}
page = PageFactory.initElements(driver, type);
runner.getInjector().injectMembers(page);
pages.put(type, page);
}
}
return (T) page.ensureLoaded(); // this will block until page is loaded
// (if implementation needs this)
}
public static void flushPageCache() {
synchronized (pages) {
pages.clear();
}
}
}