Project

General

Profile

Download (11.7 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.ClassificationTreeBlock;
27
import eu.etaxonomy.dataportal.elements.LinkElement;
28
import eu.etaxonomy.dataportal.selenium.JUnitWebDriverWait;
29
import eu.etaxonomy.dataportal.selenium.UrlLoaded;
30

    
31
public abstract class  PortalPage {
32

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

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

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

    
42
    protected WebDriver driver;
43

    
44
    protected DataPortalContext context;
45

    
46
    protected final JUnitWebDriverWait wait;
47

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

    
52

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

    
62
    private String drupalPagePath;
63

    
64
    protected URL pageUrl;
65

    
66
    // ==== WebElements === //
67

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

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

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

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

    
82
    @FindBy(id="block-cdm-dataportal-2")
83
    @CacheLookup
84
    protected WebElement searchBlockElement;
85

    
86
    @FindBy(id="block-cdm-taxontree-cdm-tree")
87
    @CacheLookup
88
    protected WebElement classificationBrowserBlock;
89

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

    
108
        this.driver = driver;
109

    
110
        this.context = context;
111

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

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

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

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

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

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

    
126
    }
127

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

    
139
        this.driver = driver;
140

    
141
        this.context = context;
142

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

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

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

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

    
154
        this.pageUrl = url;
155

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

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

    
161
    }
162

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

    
173
        this.driver = driver;
174

    
175
        this.context = context;
176

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

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

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

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

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

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

    
195
    }
196

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

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

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

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

    
226
    /**
227
     *
228
     * @return the page title
229
     * @deprecated use {@link driver#getTitle()}
230
     */
231
    @Deprecated
232
    public String getTitle() {
233
        return driver.getTitle();
234
    }
235

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

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

    
252
    public String getAuthorInformationText() {
253

    
254
        WebElement authorInformation = null;
255

    
256
        try {
257
            authorInformation  = node.findElement(By.className("submitted"));
258
        } catch (NoSuchElementException e) {
259
            // IGNORE //
260
        }
261

    
262

    
263
        if(authorInformation != null){
264
            return authorInformation.getText();
265
        } else {
266
            return null;
267
        }
268
    }
269

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

    
280
        return tabs;
281
    }
282

    
283
    public ClassificationTreeBlock getClassificationTree() {
284
        return new ClassificationTreeBlock(classificationBrowserBlock);
285
    }
286

    
287
    public void hover(WebElement element) {
288
        Actions actions = new Actions(driver);
289
        actions.moveToElement(element, 1, 1).perform();
290
        logger.debug("hovering");
291
    }
292

    
293

    
294
    /**
295
     * Returns the current URL string from the {@link WebDriver}
296
     * @return
297
     */
298
    public URL getPageURL() {
299
        return pageUrl;
300
    }
301

    
302

    
303
    /**
304
     * return the <code>scheme://domain:port</code> part of the initial url of this page.
305
     * @return
306
     */
307
    public String getInitialUrlBase() {
308
        return pageUrl.getProtocol() + "://" + pageUrl.getHost() + pageUrl.getPort();
309
    }
310

    
311
    @Override
312
    public boolean equals(Object obj) {
313
        if (PortalPage.class.isAssignableFrom(obj.getClass())) {
314
            PortalPage page = (PortalPage) obj;
315
            return this.getPageURL().toString().equals(page.getPageURL().toString());
316

    
317
        } else {
318
            return false;
319
        }
320
    }
321

    
322

    
323
    /**
324
     * @param <T>
325
     * @param link the link to click
326
     * @param isTrue see {@link org.openqa.selenium.support.ui.FluentWait#until(Function)}
327
     * @param pageType the return type
328
     * @param duration may be null, if this in null <code>waitUnit</code> will be ignored.
329
     * @param waitUnit may be null, is ignored if <code>duration</code> is null defaults to {@link TimeUnit.SECONDS}
330
     * @return
331
     * @throws SecurityException
332
     */
333
    public <T extends PortalPage> T clickLink(BaseElement element, Function<? super WebDriver, Boolean> isTrue, Class<T> pageType, Long duration, TimeUnit waitUnit) {
334

    
335
        if( pageType.getClass().equals(PortalPage.class) ) {
336
            throw new RuntimeException("Parameter pageType must be a subclass of PortalPage");
337
        }
338
        String targetWindow = null;
339
        List<String> targets = element.getLinkTargets(driver);
340
        if(targets.size() > 0){
341
            targetWindow = targets.get(0);
342
        }
343

    
344
        if(logger.isInfoEnabled() || logger.isDebugEnabled()){
345
            logger.info("clickLink() on " + element.toStringWithLinks());
346
        }
347
        element.getElement().click();
348
        if(targetWindow != null){
349
            driver.switchTo().window(targetWindow);
350
        }
351

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

    
366

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

    
378

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

    
390

    
391
    /**
392
     * replaces all underscores '_' by hyphens '-'
393
     *
394
     * @param featureName
395
     * @return
396
     */
397
    protected String normalizeClassAttribute(String featureName) {
398
        return featureName.replace('_', '-');
399
    }
400

    
401

    
402
}
(3-3/6)