/******************************************************************************* * 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.pageobjects; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.How; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.Wait; import org.openqa.selenium.support.ui.WebDriverWait; /** * This is the abstract page which should be the parent of every page object. * * <br/> * It is essential that you always implement the {@link #isDisplayed()} method. The test * should always have the following things in it:<br/><br/> * {@code AbstractPage page = PageFactory.initElements(driver, org.eclipse.skalli.selenium.pageobjects.MainHeaderPage.class);<br/> * page.{@link #isDisplayedWithExplicitWait()};}<br/><br/> * Otherwise there are problems recognizing if the page is loaded or not and if every element is on the page. * Elements which are not implemented in the {@link #isDisplayed()} method are not recognized. */ public abstract class AbstractPage { //needed to allow initialization with PageFactory @FindBy(how = How.XPATH, using = "//html") private WebElement html; /** * The time to wait for a page to load * (in seconds - system property "selenium.waitForPageToLoad.timeout" or 5 by default) */ private static final long WAIT_FOR_PAGE_TO_LOAD_TIME = Long.parseLong(System.getProperty( "selenium.waitForPageToLoad.timeout", "5")); /** * The driver */ protected WebDriver driver; /** * Creates an abstract page using the driver * @param driver The driver to be used */ public AbstractPage(WebDriver driver) { this.driver = driver; } /** * Returns whether the page is displayed or not. * <br/> * It is essential that this method is implemented for every page and that it is called. * If you only instantiate the page with the {@link org.openqa.selenium.support.PageFactory} * it is for example not recognized that the page is not accessible. * <br/> * You have to ask {@link org.openqa.selenium.WebElement#isDisplayed()} * of every {@link org.openqa.selenium.WebElement}. Otherwise it cannot be * recognized that the element you did not check is on the page or not. * @return {@code true} if the page is displayed {@code false} otherwise */ public abstract boolean isDisplayed(); /** * The return value for {@link #explicitWaitForPage()} (one of the fields initialized in the page object - not null!!!) * @return The value returned by {@link #explicitWaitForPage()} (not null!!!) */ protected abstract WebElement explicitWaitReturn(); /** * Explicitly waits for the page to load (until {@link #isDisplayed()} returns {@code true}) */ public void explicitWaitForPage() { Wait<WebDriver> wait = new WebDriverWait(driver, WAIT_FOR_PAGE_TO_LOAD_TIME); wait.until(new ExpectedCondition<WebElement>() { @Override public WebElement apply(WebDriver driver) { try { if (isDisplayed()) { return explicitWaitReturn(); } } catch (Exception e) { //avoid that any exception causes the wait to be stopped //print out the error message to identify which UI element cannot be found System.out.println(e.getMessage()); } return null; } }); } /** * Explicitly waits for the page to load and returns whether the page is displayed or not * @return Whether the page is displayed or not after the explicit wait */ public boolean isDisplayedWithExplicitWait() { explicitWaitForPage(); return isDisplayed(); } /** * Returns the title of the page currently loaded by the {@link org.openqa.selenium.WebDriver} * @return The title of the page */ public String getTitle() { return driver.getTitle(); } }