Project

General

Profile

Download (10 KB) Statistics
| Branch: | Tag: | Revision:
1
package eu.etaxonomy.dataportal.pages;
2

    
3
import java.lang.reflect.Constructor;
4
import java.net.MalformedURLException;
5
import java.net.URL;
6
import java.util.ArrayList;
7
import java.util.List;
8
import java.util.concurrent.TimeUnit;
9

    
10
import org.apache.log4j.Logger;
11
import org.openqa.selenium.By;
12
import org.openqa.selenium.NoSuchElementException;
13
import org.openqa.selenium.WebDriver;
14
import org.openqa.selenium.WebElement;
15
import org.openqa.selenium.interactions.Actions;
16
import org.openqa.selenium.support.CacheLookup;
17
import org.openqa.selenium.support.FindBy;
18
import org.openqa.selenium.support.FindBys;
19
import org.openqa.selenium.support.PageFactory;
20
import org.openqa.selenium.support.ui.WebDriverWait;
21

    
22
import com.google.common.base.Function;
23

    
24
import eu.etaxonomy.dataportal.DataPortalContext;
25
import eu.etaxonomy.dataportal.elements.BaseElement;
26
import eu.etaxonomy.dataportal.elements.LinkElement;
27
import eu.etaxonomy.dataportal.selenium.JUnitWebDriverWait;
28
import eu.etaxonomy.dataportal.selenium.UrlLoaded;
29

    
30
public abstract class  PortalPage {
31

    
32
	/**
33
	 *
34
	 */
35
	public static final int WAIT_SECONDS = 25;
36

    
37
	public static final Logger logger = Logger.getLogger(PortalPage.class);
38

    
39
	protected final static String DRUPAL_PAGE_QUERY_BASE = "?q=";
40

    
41
	protected WebDriver driver;
42

    
43
	protected DataPortalContext context;
44

    
45
	protected final JUnitWebDriverWait wait;
46

    
47
	public WebDriverWait getWait() {
48
		return wait;
49
	}
50

    
51

    
52
	/**
53
	 * Implementations of this method will supply the relative
54
	 * path to the Drupal page. This path will usally have the form
55
	 * <code>cdm_dataportal/{nodetype}</code>. For example the taxon pages all
56
	 * have the page base <code>cdm_dataportal/taxon</code>
57
	 * @return
58
	 */
59
	protected abstract String getDrupalPageBase();
60

    
61
	private String drupalPagePath;
62

    
63
	protected URL pageUrl;
64

    
65
	// ==== WebElements === //
66

    
67
	@FindBy(id="cdm_dataportal.node")
68
	protected WebElement portalContent;
69

    
70
	@FindBy(tagName="title")
71
	@CacheLookup
72
	protected WebElement title;
73

    
74
	@FindBy(className="node")
75
	protected WebElement node;
76

    
77
	@FindBys({@FindBy(id="tabs-wrapper"), @FindBy(className="primary")})
78
	@CacheLookup
79
	protected WebElement primaryTabs;
80

    
81
	@FindBy(id="block-cdm_dataportal-2")
82
	@CacheLookup
83
	protected WebElement searchBlockElement;
84

    
85
	@FindBy(id="block-cdm_taxontree-cdm_tree")
86
	@CacheLookup
87
	protected WebElement classificationBrowserBlock;
88

    
89
	/**
90
	 * Creates a new PortaPage. Implementations of this class will provide the base path of the page by
91
	 * implementing the method {@link #getDrupalPageBase()}. The constructor argument <code>pagePathSuffix</code>
92
	 * specifies the specific page to navigate to. For example:
93
	 * <ol>
94
	 * <li>{@link #getDrupalPageBase()} returns <code>/cdm_dataportal/taxon</code></li>
95
	 * <li><code>pagePathSuffix</code> gives <code>7fe8a8b6-b0ba-4869-90b3-177b76c1753f</code></li>
96
	 * </ol>
97
	 * Both are combined to form the URL pathelement <code>/cdm_dataportal/taxon/7fe8a8b6-b0ba-4869-90b3-177b76c1753f</code>
98
	 *
99
	 *
100
	 * @param driver
101
	 * @param context
102
	 * @param pagePathSuffix
103
	 * @throws MalformedURLException
104
	 */
105
	public PortalPage(WebDriver driver, DataPortalContext context, String pagePathSuffix) throws MalformedURLException {
106

    
107
		this.driver = driver;
108

    
109
		this.context = context;
110

    
111
		this.wait = new JUnitWebDriverWait(driver, WAIT_SECONDS);
112

    
113
		this.drupalPagePath = getDrupalPageBase() + (pagePathSuffix != null ? "/" + pagePathSuffix: "");
114

    
115
		this.pageUrl = new URL(context.getBaseUri().toString() + DRUPAL_PAGE_QUERY_BASE + drupalPagePath);
116

    
117
		// tell browser to navigate to the page
118
		driver.get(pageUrl.toString());
119

    
120
	    // This call sets the WebElement fields.
121
	    PageFactory.initElements(driver, this);
122

    
123
		logger.info("loading " + pageUrl);
124

    
125
	}
126

    
127
	/**
128
	 * Creates a new PortaPage at given URL location. An Exception is thrown if
129
	 * this URL is not matching the expected URL for the specific page type.
130
	 *
131
	 * @param driver
132
	 * @param context
133
	 * @param url
134
	 * @throws Exception
135
	 */
136
	public PortalPage(WebDriver driver, DataPortalContext context, URL url) throws Exception {
137

    
138
		this.driver = driver;
139

    
140
		this.context = context;
141

    
142
		this.wait = new JUnitWebDriverWait(driver, 25);
143

    
144
		this.pageUrl = new URL(context.getBaseUri().toString());
145

    
146
		// tell browser to navigate to the given URL
147
		driver.get(url.toString());
148

    
149
		if(!isOnPage()){
150
			throw new Exception("Not on the expected portal page ( current: " + driver.getCurrentUrl() + ", expected: " +  pageUrl + " )");
151
		}
152

    
153
		this.pageUrl = url;
154

    
155
		logger.info("loading " + pageUrl);
156

    
157
	    // This call sets the WebElement fields.
158
	    PageFactory.initElements(driver, this);
159

    
160
	}
161

    
162
	/**
163
	 * Creates a new PortaPage at the WebDrivers current URL location. An Exception is thrown if
164
	 * driver.getCurrentUrl() is not matching the expected URL for the specific page type.
165
	 *
166
	 * @param driver
167
	 * @param context
168
	 * @throws Exception
169
	 */
170
	public PortalPage(WebDriver driver, DataPortalContext context) throws Exception {
171

    
172
		this.driver = driver;
173

    
174
		this.context = context;
175

    
176
		this.wait = new JUnitWebDriverWait(driver, 25);
177

    
178
		// preliminary set the pageUrl to the base path of this page, this is used in the next setp to check if the
179
		// driver.getCurrentUrl() is a sub path of the base path
180
		this.pageUrl = new URL(context.getBaseUri().toString());
181

    
182
		if(!isOnPage()){
183
			throw new Exception("Not on the expected portal page ( current: " + driver.getCurrentUrl() + ", expected: " +  pageUrl + " )");
184
		}
185

    
186
		// now set the real URL
187
		this.pageUrl = new URL(driver.getCurrentUrl());
188

    
189
		logger.info("loading " + pageUrl);
190

    
191
	    // This call sets the WebElement fields.
192
	    PageFactory.initElements(driver, this);
193

    
194
	}
195

    
196
	/**
197
	 * @return
198
	 */
199
	protected boolean isOnPage() {
200
		return driver.getCurrentUrl().startsWith(pageUrl.toString());
201
	}
202

    
203
	/**
204
	 * navigate and reload the page if not jet there
205
	 */
206
	public void get() {
207
		if(!driver.getCurrentUrl().equals(pageUrl.toString())){
208
			driver.get(pageUrl.toString());
209
			wait.until(new UrlLoaded(pageUrl.toString()));
210
			PageFactory.initElements(driver, this);
211
		}
212
	}
213

    
214
	/**
215
	 * go back in history
216
	 */
217
	public void back() {
218
		driver.navigate().back();
219
	}
220

    
221
	public String getDrupalPagePath() {
222
		return drupalPagePath;
223
	}
224

    
225
	/**
226
	 * returns the string from the <code>title</code> tag.
227
	 * @return
228
	 */
229
	public String getTitle() {
230
		return title.getText();
231
	}
232

    
233
	/**
234
	 * returns the warning messages from the Drupal message box
235
	 * @return
236
	 */
237
	public String getWarnings() {
238
		return null; //TODO unimplemented
239
	}
240

    
241
	/**
242
	 * returns the error messages from the Drupal message box
243
	 * @return
244
	 */
245
	public String getErrors() {
246
		return null; //TODO unimplemented
247
	}
248

    
249
	public String getAuthorInformationText() {
250

    
251
		WebElement authorInformation = null;
252

    
253
		try {
254
			authorInformation  = node.findElement(By.className("submitted"));
255
		} catch (NoSuchElementException e) {
256
			// IGNORE //
257
		}
258

    
259

    
260
		if(authorInformation != null){
261
			return authorInformation.getText();
262
		} else {
263
			return null;
264
		}
265
	}
266

    
267
	public List<LinkElement> getPrimaryTabs(){
268
		List<LinkElement> tabs = new ArrayList<LinkElement>();
269
		List<WebElement> links = primaryTabs.findElements(By.tagName("a"));
270
		for(WebElement a : links) {
271
			WebElement renderedLink = a;
272
			if(renderedLink.isDisplayed()){
273
				tabs.add(new LinkElement(renderedLink));
274
			}
275
		}
276

    
277
		return tabs;
278
	}
279

    
280
	public void hover(WebElement element) {
281
		Actions actions = new Actions(driver);
282
		actions.moveToElement(element, 1, 1).perform();
283
		logger.debug("hovering");
284
	}
285

    
286

    
287
	/**
288
	 * Returns the current URL string from the {@link WebDriver}
289
	 * @return
290
	 */
291
	public URL getPageURL() {
292
		return pageUrl;
293
	}
294

    
295

    
296
	/**
297
	 * return the <code>scheme://domain:port</code> part of the initial url of this page.
298
	 * @return
299
	 */
300
	public String getInitialUrlBase() {
301
		return pageUrl.getProtocol() + "://" + pageUrl.getHost() + pageUrl.getPort();
302
	}
303

    
304
	public boolean equals(Object obj) {
305
		if (PortalPage.class.isAssignableFrom(obj.getClass())) {
306
			PortalPage page = (PortalPage) obj;
307
			return this.getPageURL().toString().equals(page.getPageURL().toString());
308

    
309
		} else {
310
			return false;
311
		}
312
	}
313

    
314

    
315
	/**
316
	 * @param <T>
317
	 * @param link the link to click
318
	 * @param isTrue see {@link org.openqa.selenium.support.ui.FluentWait#until(Function)}
319
	 * @param type the return type
320
	 * @param duration may be null, if this in null <code>waitUnit</code> will be ignored.
321
	 * @param waitUnit may be null, is ignored if <code>duration</code> is null defaults to {@link TimeUnit.SECONDS}
322
	 * @return
323
	 * @throws SecurityException
324
	 */
325
	public <T extends PortalPage> T clickLink(BaseElement element, Function<? super WebDriver, Boolean> isTrue, Class<T> type, Long duration, TimeUnit waitUnit) {
326

    
327
		String targetWindow = null;
328

    
329

    
330
		if(targetWindow == null){
331
			if(element instanceof LinkElement){
332
				targetWindow = element.getElement().getAttribute("target");
333
			} else {
334
				try {
335
					targetWindow = element.getElement().findElement(By.xpath("./a[@target]")).getAttribute("target");
336
				} catch (NoSuchElementException e) {
337
					logger.debug("No target window found");
338
					/* IGNORE */
339
				}
340
			}
341

    
342
		}
343

    
344
		logger.info("clicking on " + element + (targetWindow == null? "" : " with target window: '" + targetWindow + "'"));
345

    
346
		element.getElement().click();
347
		if(targetWindow != null){
348
			driver.switchTo().window(targetWindow);
349
		}
350

    
351
		try {
352
			if(duration != null){
353
				if(waitUnit == null){
354
					waitUnit = TimeUnit.SECONDS;
355
				}
356
				wait.withTimeout(duration, waitUnit).until(isTrue);
357
			} else {
358
				wait.until(isTrue);
359
			}
360
		} catch (AssertionError timeout){
361
			logger.info("current WindowHandles:" + driver.getWindowHandles());
362
			throw timeout;
363
		}
364

    
365

    
366
		Constructor<T> constructor;
367
		T pageInstance;
368
		try {
369
			constructor = type.getConstructor(WebDriver.class, DataPortalContext.class);
370
			pageInstance = constructor.newInstance(driver, context);
371
		} catch (Exception e) {
372
			throw new RuntimeException(e);
373
		}
374
		return pageInstance;
375
	}
376

    
377

    
378
	/**
379
	 * @param <T>
380
	 * @param link the link to click
381
	 * @param isTrue see {@link org.openqa.selenium.support.ui.FluentWait#until(Function)}
382
	 * @param type the return type
383
	 * @return
384
	 */
385
	public <T extends PortalPage> T clickLink(BaseElement element, Function<? super WebDriver, Boolean> isTrue, Class<T> type) {
386
		return clickLink(element, isTrue, type, null, null);
387
	}
388

    
389

    
390
}
(3-3/6)