/* * This is eMonocot, a global online biodiversity information resource. * * Copyright © 2011–2015 The Board of Trustees of the Royal Botanic Gardens, Kew and The University of Oxford * * eMonocot is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * eMonocot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * The complete text of the GNU Affero General Public License is in the source repository as the file * ‘COPYING’. It is also available from <http://www.gnu.org/licenses/>. */ package org.emonocot.portal.driver; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.emonocot.portal.remoting.IdentificationKeyDaoImpl; import org.emonocot.portal.remoting.ImageDaoImpl; import org.emonocot.test.TestDataManager; import org.openqa.selenium.By; import org.openqa.selenium.Cookie; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.NoSuchElementException; 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.PageFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author ben */ public class PageObject { private Pattern pattern = Pattern.compile("^(.*?);jsessionid=[A-Z0-9]+$"); /** * */ @FindBy(how = How.TAG_NAME, using = "footer") private WebElement foot; /** * */ @FindBy(how = How.ID_OR_NAME, using = "identify-box") private WebElement identifyBox; /** * */ @FindBy(how = How.ID_OR_NAME, using = "classify-box") private WebElement classifyBox; /** * */ @FindBy(how = How.CLASS_NAME, using = "navbar") private WebElement nav; /** * */ private static final Integer AJAX_WAIT_STEP = 100; /** * */ private static Logger logger = LoggerFactory.getLogger(PageObject.class); /** * @return the identify link */ public final Identify selectIdentifyLink() { return openAs( identifyBox.findElement(By.linkText("identification features")).getAttribute("href"), Identify.class); } /** * @return the identify link */ public final Identify selectClassifyLink() { return openAs( classifyBox.findElement(By.linkText("classification features")).getAttribute("href"), Identify.class); } /** * */ @FindBy(how = How.TAG_NAME, using = "a") private List<WebElement> links; /** * */ protected WebDriver webDriver; /** * */ protected ImageDaoImpl imageDao; /** * */ protected IdentificationKeyDaoImpl keyDao; /** * */ private String baseUri; private String host; private String basePath; private int port; /** * */ protected TestDataManager testDataManager; /** * @param newBaseUri * Set the base Uri */ public final void setBaseUri(final String newBaseUri) { this.baseUri = newBaseUri; } /** * @return the base uri */ public final String getBaseUri() { return baseUri; } /** * @param <T> * The type of page * @param address * the url of the page * @param pageClass * the class of the page * @return the page */ protected final <T extends PageObject> T openAs(final String address, final Class<T> pageClass) { open(address); Pattern loginPattern = Pattern.compile(".*/login.*"); if (loginPattern.matcher(webDriver.getCurrentUrl()).matches() && !pageClass.equals(Login.class)) { Login loginPage = pageObjectInstance(Login.class); loginPage.setBaseUri(baseUri); loginPage.testDataManager = this.testDataManager; loginPage.webDriver = this.webDriver; loginPage.imageDao = this.imageDao; loginPage.keyDao = this.keyDao; throw new RequiresLoginException(loginPage); } return getPage(pageClass); } /** * @param <T> * The type of page * @param pageClass * the class of the page * @return the page */ protected final <T extends PageObject> T getPage(final Class<T> pageClass) { T pageObject = pageObjectInstance(pageClass); pageObject.setBaseUri(baseUri); pageObject.setHost(host); pageObject.setPort(port); pageObject.setBasePath(basePath); pageObject.testDataManager = this.testDataManager; pageObject.webDriver = this.webDriver; pageObject.imageDao = this.imageDao; pageObject.keyDao = this.keyDao; return pageObject; } /** * @param initialPause * Set the initial wait time */ public final void waitForAjax(final Integer initialPause) { try { Thread.sleep(initialPause); while (true) { Boolean ajaxIsComplete = (Boolean) ((JavascriptExecutor) webDriver) .executeScript("return jQuery.active == 0"); if (ajaxIsComplete) { break; } Thread.sleep(AJAX_WAIT_STEP); } } catch (InterruptedException ie) { logger.error(ie.getMessage()); } } /** * @param <T> * The type of page * @param pageClass * Set the page class * @return an instance of class T */ private <T extends PageObject> T pageObjectInstance(final Class<T> pageClass) { return PageFactory.initElements(webDriver, pageClass); } /** * @param address * Set hte address */ private void open(final String address) { webDriver.navigate().to(address); } /** * @return the web driver */ public final WebDriver getWebDriver() { return webDriver; } /** * Assumption that we're handling authentication via tomcat and using * Cookies. */ public final void disableAuthentication() { Cookie cookie = webDriver.manage().getCookieNamed("jsessionid"); if (cookie != null) { webDriver.manage().deleteCookie(cookie); } } /** * @return the current (baseURI-relative including preceding slash) uri or * null if the URI is malformed */ public final String getUri() { try { java.net.URI uri = new java.net.URI(webDriver.getCurrentUrl()); String basePath = new java.net.URI(getBaseUri()).getPath(); String relPath = uri.getPath().replace(basePath, ""); relPath = relPath.startsWith("/") ? relPath.substring(1) : relPath; Matcher matcher = pattern.matcher(relPath); if(matcher.matches()) { relPath = matcher.group(1); } return relPath; } catch (java.net.URISyntaxException e) { e.printStackTrace(); return null; } } /** * @return the login page */ public final Login selectLoginLink() { return this.openAs( nav.findElement(By.linkText("Sign in")).getAttribute("href"), Login.class); } /** * @return true, if the user is logged in */ public final Boolean loggedIn() { WebElement userMenu = nav.findElement(By.cssSelector("#menuUser")); return (userMenu != null); } /** * */ public final void logOut() { try { openAs(getBaseUri() + "/logout", Index.class); } catch (Exception e) { logger.debug(e.getMessage()); } } /** * @return the info message */ public final String getInfoMessage() { WebElement webElement = webDriver.findElement(By .cssSelector(".alert.info p")); return webElement.getText(); } /** * @param text * Set the link text * @param clazz * Set the expected page * @return the page object */ public final PageObject selectLink(final String text, final Class<? extends PageObject> clazz) { return this.openAs(this.webDriver.findElement(By.linkText(text)) .getAttribute("href"), clazz); } /** * @return the about page */ public final About selectAboutLink() { return openAs( foot.findElement(By.linkText("About us")).getAttribute("href"), About.class); } public final TermsOfUse selectTermsOfUseLink() { return openAs( foot.findElement(By.linkText("Terms of Use")).getAttribute("href"), TermsOfUse.class); } /** * @return the contact page */ public final String getContactLink() { return foot.findElement(By.xpath("div/div/div/ul/li/ul/li/a[@class='contactLinkOverlay']")).getAttribute("href"); } /** * @param text partial text of link to search for * @return false if there is a NoSuchElementException is thrown * true otherwise */ public final boolean isLinkPresent(String text) { try { webDriver.findElement(By.partialLinkText(text)); // if an element is found return true; } catch (NoSuchElementException e) { return false; } } /** * @param text * the text of the link * @return the target of the link if it is found on this page */ public PageObject selectLink(String text) { return selectLink(text, PageObject.class); } /** * @param elementId * @return Whether an element with this id is visible */ public boolean isElementVisible(String elementId) { try { WebElement element = webDriver.findElement(By.id(elementId)); return element.isDisplayed(); } catch (NoSuchElementException e) { return false; } } /** * @return the footer icons arrangement */ public final List<List<String>> getFooterIconsArrangement() { List<List<String>> returnRows = new ArrayList<List<String>>(); List<WebElement> footerRows = foot.findElement(By.id("footer-icons")).findElements(By.className("nav")); for (WebElement we : footerRows) { List<String> returnRow = new ArrayList<String>(); for (WebElement img : we.findElements(By.tagName("img"))) { returnRow.add(img.getAttribute("alt")); } returnRows.add(returnRow); } return returnRows; } /** * @param paragraphNameOrId * @return */ public String paragraphText(String paragraphNameOrId) { WebElement element = null; try{ logger.info("Attempting to find element by id:" + paragraphNameOrId); element = webDriver.findElement(By.id(paragraphNameOrId)); } catch (NoSuchElementException e0) { logger.info("No element with id:" + paragraphNameOrId + ". Attempting to find element with this name"); try { element = webDriver.findElement(By.name(paragraphNameOrId)); } catch (NoSuchElementException e1) { logger.warn("Unable to find element with either id or name:" + paragraphNameOrId, e1); element = null; } } if(element == null) { return null; } else { return element.getText(); } } /** * @return The source of the page. Dependant on the implementing class, this * can be the source when the page was retrieved, the page as modified by script * or some other representation of the DOM */ public String getText() { return webDriver.getPageSource(); } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getBasePath() { return basePath; } public void setBasePath(String basePath) { this.basePath = basePath; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } }