001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 */ 019package org.nuxeo.runtime.test.runner.web; 020 021import java.net.MalformedURLException; 022import java.net.URL; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026 027import javax.inject.Inject; 028 029import org.nuxeo.runtime.test.runner.FeaturesRunner; 030import org.openqa.selenium.By; 031import org.openqa.selenium.NotFoundException; 032import org.openqa.selenium.WebDriver; 033import org.openqa.selenium.WebDriverException; 034import org.openqa.selenium.WebElement; 035import org.openqa.selenium.support.PageFactory; 036import org.openqa.selenium.support.ui.ExpectedCondition; 037import org.openqa.selenium.support.ui.WebDriverWait; 038 039/** 040 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 041 */ 042public abstract class WebPage { 043 044 /** 045 * Can be used by tests as default timeouts. This way you can change these values to change all the timeout in the 046 * tests. DEFAULT_TIMEOUT is used for regular timeouts (loading an ajax page an ajax dialog etc.) while BIG_TIMEOUT 047 * should be used for pages that are slower (like the home of a GWT application) 048 */ 049 public static int DEFAULT_TIMEOUT = 5; 050 051 public static int BIG_TIMEOUT = 15; 052 053 private static final Map<Class<?>, WebPage> pages = new HashMap<Class<?>, WebPage>(); 054 055 @Inject 056 protected Configuration config; 057 058 @Inject 059 protected WebDriver driver; 060 061 @Inject 062 protected FeaturesRunner runner; 063 064 /** 065 * Should be overridden by dynamic page (using ajax) to wait until the page is completely loaded By default nothing 066 * is done (page is assumed to be loaded) 067 * 068 * @return the page itself 069 */ 070 public WebPage ensureLoaded() { 071 return this; // do nothing by default 072 } 073 074 public Configuration getConfiguration() { 075 return config; 076 } 077 078 public WebDriver getDriver() { 079 return driver; 080 } 081 082 public FeaturesRunner getRunner() { 083 return runner; 084 } 085 086 public void home() { 087 driver.get(config.home); 088 } 089 090 public void to(String path) { 091 if (path.contains("://")) { 092 driver.get(path); 093 } else { 094 try { 095 URL url = new URL(new URL(config.home), path); 096 driver.navigate().to(url); 097 } catch (MalformedURLException e) { 098 throw new WebDriverException(e); 099 } 100 } 101 } 102 103 public boolean hasElement(final By by) { 104 try { 105 driver.findElement(by); 106 return true; 107 } catch (WebDriverException e) { 108 return false; 109 } 110 } 111 112 public boolean hasElement(final By by, int timeoutInSeconds) { 113 try { 114 findElement(by, timeoutInSeconds); 115 return true; 116 } catch (WebDriverException e) { 117 return false; 118 } 119 } 120 121 public WebElement findElement(final By by) { 122 return driver.findElement(by); 123 } 124 125 public List<WebElement> findElements(final By by) { 126 return driver.findElements(by); 127 } 128 129 public WebElement findElement(final By by, int timeOutInSeconds) { 130 return waitUntilElementFound(by, timeOutInSeconds); 131 } 132 133 public WebElement waitUntilElementFound(final By by, int timeOutInSeconds) { 134 try { 135 return findElement(by); // try once first 136 } catch (NotFoundException e) { 137 return new WebDriverWait(driver, timeOutInSeconds).until(new ExpectedCondition<WebElement>() { 138 @Override 139 public WebElement apply(WebDriver arg0) { 140 return driver.findElement(by); 141 } 142 }); 143 } 144 } 145 146 public void waitUntilElementNotFound(final By by, int timeOutInSeconds) { 147 try { 148 findElement(by); // try once first 149 new WebDriverWait(driver, timeOutInSeconds).until(new ExpectedCondition<Boolean>() { 150 @Override 151 public Boolean apply(WebDriver arg0) { 152 try { 153 driver.findElement(by); 154 return Boolean.FALSE; 155 } catch (NotFoundException e) { 156 return Boolean.TRUE; 157 } 158 } 159 }); 160 } catch (NotFoundException e) { 161 } 162 } 163 164 @SuppressWarnings("unchecked") 165 public <T extends WebPage> T getPage(Class<T> type) { 166 T page = (T) pages.get(type); 167 if (page == null) { 168 synchronized (pages) { 169 page = (T) pages.get(type); 170 if (page != null) { 171 return page; 172 } 173 page = PageFactory.initElements(driver, type); 174 runner.getInjector().injectMembers(page); 175 pages.put(type, page); 176 } 177 } 178 return (T) page.ensureLoaded(); // this will block until page is loaded 179 // (if implementation needs this) 180 } 181 182 public static void flushPageCache() { 183 synchronized (pages) { 184 pages.clear(); 185 } 186 } 187 188}