Project

General

Profile

Download (11.5 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.bcel.verifier.exc.LinkingConstraintException;
11
import org.apache.commons.lang.StringUtils;
12
import org.apache.log4j.Logger;
13
import org.openqa.selenium.By;
14
import org.openqa.selenium.NoSuchElementException;
15
import org.openqa.selenium.WebDriver;
16
import org.openqa.selenium.WebElement;
17
import org.openqa.selenium.interactions.Actions;
18
import org.openqa.selenium.support.CacheLookup;
19
import org.openqa.selenium.support.FindBy;
20
import org.openqa.selenium.support.FindBys;
21
import org.openqa.selenium.support.PageFactory;
22
import org.openqa.selenium.support.ui.WebDriverWait;
23

    
24
import sun.swing.StringUIClientPropertyKey;
25

    
26
import com.google.common.base.Function;
27

    
28
import eu.etaxonomy.dataportal.DataPortalContext;
29
import eu.etaxonomy.dataportal.elements.BaseElement;
30
import eu.etaxonomy.dataportal.elements.ClassificationTreeBlock;
31
import eu.etaxonomy.dataportal.elements.LinkElement;
32
import eu.etaxonomy.dataportal.selenium.JUnitWebDriverWait;
33
import eu.etaxonomy.dataportal.selenium.UrlLoaded;
34

    
35
public abstract class  PortalPage {
36

    
37
    /**
38
     *
39
     */
40
    public static final int WAIT_SECONDS = 25;
41

    
42
    public static final Logger logger = Logger.getLogger(PortalPage.class);
43

    
44
    protected final static String DRUPAL_PAGE_QUERY_BASE = "?q=";
45

    
46
    protected WebDriver driver;
47

    
48
    protected DataPortalContext context;
49

    
50
    protected final JUnitWebDriverWait wait;
51

    
52
    public WebDriverWait getWait() {
53
        return wait;
54
    }
55

    
56

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

    
66
    private String drupalPagePath;
67

    
68
    protected URL pageUrl;
69

    
70
    // ==== WebElements === //
71

    
72
    @FindBy(id="cdm_dataportal.node")
73
    protected WebElement portalContent;
74

    
75
    @FindBy(tagName="title")
76
    @CacheLookup
77
    protected WebElement title;
78

    
79
    @FindBy(className="node")
80
    protected WebElement node;
81

    
82
    @FindBys({@FindBy(id="tabs-wrapper"), @FindBy(className="primary")})
83
    @CacheLookup
84
    protected WebElement primaryTabs;
85

    
86
    @FindBy(id="block-cdm-dataportal-2")
87
    @CacheLookup
88
    protected WebElement searchBlockElement;
89

    
90
    @FindBy(id="block-cdm-taxontree-cdm-tree")
91
    @CacheLookup
92
    protected WebElement classificationBrowserBlock;
93

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

    
112
        this.driver = driver;
113

    
114
        this.context = context;
115

    
116
        this.wait = new JUnitWebDriverWait(driver, WAIT_SECONDS);
117

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

    
120
        this.pageUrl = new URL(context.getBaseUri().toString() + DRUPAL_PAGE_QUERY_BASE + drupalPagePath);
121

    
122
        // tell browser to navigate to the page
123
        driver.get(pageUrl.toString());
124

    
125
        // This call sets the WebElement fields.
126
        PageFactory.initElements(driver, this);
127

    
128
        logger.info("loading " + pageUrl);
129

    
130
    }
131

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

    
143
        this.driver = driver;
144

    
145
        this.context = context;
146

    
147
        this.wait = new JUnitWebDriverWait(driver, 25);
148

    
149
        this.pageUrl = new URL(context.getBaseUri().toString());
150

    
151
        // tell browser to navigate to the given URL
152
        driver.get(url.toString());
153

    
154
        if(!isOnPage()){
155
            throw new Exception("Not on the expected portal page ( current: " + driver.getCurrentUrl() + ", expected: " +  pageUrl + " )");
156
        }
157

    
158
        this.pageUrl = url;
159

    
160
        logger.info("loading " + pageUrl);
161

    
162
        // This call sets the WebElement fields.
163
        PageFactory.initElements(driver, this);
164

    
165
    }
166

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

    
177
        this.driver = driver;
178

    
179
        this.context = context;
180

    
181
        this.wait = new JUnitWebDriverWait(driver, 25);
182

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

    
187
        if(!isOnPage()){
188
            throw new Exception("Not on the expected portal page ( current: " + driver.getCurrentUrl() + ", expected: " +  pageUrl + " )");
189
        }
190

    
191
        // now set the real URL
192
        this.pageUrl = new URL(driver.getCurrentUrl());
193

    
194
        logger.info("loading " + pageUrl);
195

    
196
        // This call sets the WebElement fields.
197
        PageFactory.initElements(driver, this);
198

    
199
    }
200

    
201
    /**
202
     * @return
203
     */
204
    protected boolean isOnPage() {
205
        return driver.getCurrentUrl().startsWith(pageUrl.toString());
206
    }
207

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

    
219
    /**
220
     * go back in history
221
     */
222
    public void back() {
223
        driver.navigate().back();
224
    }
225

    
226
    public String getDrupalPagePath() {
227
        return drupalPagePath;
228
    }
229

    
230
    /**
231
     * returns the string from the <code>title</code> tag.
232
     * @return
233
     */
234
    public String getTitle() {
235
        return title.getText();
236
    }
237

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

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

    
254
    public String getAuthorInformationText() {
255

    
256
        WebElement authorInformation = null;
257

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

    
264

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

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

    
282
        return tabs;
283
    }
284

    
285
    public ClassificationTreeBlock getClassificationTree() {
286
        return new ClassificationTreeBlock(classificationBrowserBlock);
287
    }
288

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

    
295

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

    
304

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

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

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

    
323

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

    
336
        String targetWindow = null;
337
        List<String> targets = element.getLinkTargets();
338
        if(targets.size() > 0){
339
            targetWindow = targets.get(0);
340
        }
341

    
342
        if(logger.isInfoEnabled()){
343
            logger.info("clicking on " + element.toStringWithLinks());
344
        }
345
        element.getElement().click();
346
        if(targetWindow != null){
347
            driver.switchTo().window(targetWindow);
348
        }
349

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

    
364

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

    
376

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

    
388

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

    
399

    
400
}
(3-3/6)