001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Sun Seng David TAN
016 *     Florent Guillaume
017 *     Antoine Taillefer
018 */
019package org.nuxeo.functionaltests.pages;
020
021import static org.junit.Assert.assertNotNull;
022
023import java.util.List;
024
025import org.nuxeo.functionaltests.AbstractTest;
026import org.nuxeo.functionaltests.AjaxRequestManager;
027import org.nuxeo.functionaltests.Assert;
028import org.nuxeo.functionaltests.Locator;
029import org.nuxeo.functionaltests.fragment.WebFragment;
030import org.openqa.selenium.By;
031import org.openqa.selenium.NoSuchElementException;
032import org.openqa.selenium.NotFoundException;
033import org.openqa.selenium.WebDriver;
034import org.openqa.selenium.WebElement;
035import org.openqa.selenium.support.FindBy;
036import org.openqa.selenium.support.ui.ExpectedConditions;
037import org.openqa.selenium.support.ui.Select;
038import org.openqa.selenium.support.ui.WebDriverWait;
039
040/**
041 * Base functions for all pages.
042 */
043public abstract class AbstractPage {
044
045    @FindBy(xpath = "//div[@id='nxw_userMenuActions_panel']/ul/li/span")
046    public WebElement userServicesForm;
047
048    protected WebDriver driver;
049
050    public AbstractPage(WebDriver driver) {
051        this.driver = driver;
052    }
053
054    /**
055     * Returns true if corresponding element is found in the test page.
056     *
057     * @since 5.7
058     */
059    public boolean hasElement(By by) {
060        return Assert.hasElement(by);
061    }
062
063    public <T> T get(String url, Class<T> pageClassToProxy) {
064        return AbstractTest.get(url, pageClassToProxy);
065    }
066
067    public <T> T asPage(Class<T> pageClassToProxy) {
068        return AbstractTest.asPage(pageClassToProxy);
069    }
070
071    public <T extends WebFragment> T getWebFragment(By by, Class<T> webFragmentClass) {
072        return AbstractTest.getWebFragment(by, webFragmentClass);
073    }
074
075    public <T extends WebFragment> T getWebFragment(WebElement element, Class<T> webFragmentClass) {
076        return AbstractTest.getWebFragment(element, webFragmentClass);
077    }
078
079    /**
080     * Gets the info feedback message.
081     *
082     * @return the message if any or an empty string.
083     * @deprecated since 5.8
084     */
085    @Deprecated
086    public String getFeedbackMessage() {
087        String ret;
088        try {
089            ret = findElementWithTimeout(By.xpath("//li[@class=\"errorFeedback\"]")).getText();
090        } catch (NoSuchElementException e) {
091            ret = "";
092        }
093        return ret.trim();
094    }
095
096    /**
097     * Returns the error feedback message.
098     * <p>
099     * If there are more than one error message, always return the second one (not interested by 'Please correct errors'
100     * message).
101     *
102     * @since 5.8
103     */
104    public String getErrorFeedbackMessage() {
105        String ret = "";
106        try {
107            List<WebElement> elements = findElementsWithTimeout(
108                    By.xpath("//div[contains(@class, 'errorFeedback')]/div[@class='ambiance-title']"));
109            if (elements.size() == 1) {
110                ret = elements.get(0).getText();
111            } else if (elements.size() > 1) {
112                ret = elements.get(1).getText();
113            }
114        } catch (NoSuchElementException e) {
115            ret = "";
116        }
117        return ret.trim();
118    }
119
120    /**
121     * Gets the top bar navigation sub page.
122     */
123    public HeaderLinksSubPage getHeaderLinks() {
124        assertNotNull(userServicesForm);
125        return asPage(HeaderLinksSubPage.class);
126    }
127
128    /**
129     * Returns the fancy box content web element
130     *
131     * @since 5.7
132     */
133    public WebElement getFancyBoxContent() {
134        // make sure the fancybox content is loaded
135        WebElement fancyBox = findElementWithTimeout(By.id("fancybox-content"));
136        WebDriverWait wait = new WebDriverWait(driver, AbstractTest.LOAD_TIMEOUT_SECONDS);
137        wait.until(ExpectedConditions.visibilityOf(fancyBox));
138        return fancyBox;
139    }
140
141    /**
142     * Finds the first {@link WebElement} using the given method, with a timeout.
143     *
144     * @param by the locating mechanism
145     * @param timeout the timeout in milliseconds
146     * @return the first matching element on the current page, if found
147     * @throws NoSuchElementException when not found
148     */
149    public WebElement findElementWithTimeout(By by, int timeout) throws NoSuchElementException {
150        return Locator.findElementWithTimeout(by, timeout);
151    }
152
153    /**
154     * Finds the first {@link WebElement} using the given method, with a timeout.
155     *
156     * @param by the locating mechanism
157     * @param timeout the timeout in milliseconds
158     * @param parentElement find from the element
159     * @return the first matching element on the current page, if found
160     * @throws NoSuchElementException when not found
161     */
162    public WebElement findElementWithTimeout(By by, int timeout, WebElement parentElement)
163            throws NoSuchElementException {
164        return Locator.findElementWithTimeout(by, timeout, parentElement);
165    }
166
167    /**
168     * Finds the first {@link WebElement} using the given method, with a timeout.
169     *
170     * @param by the locating mechanism
171     * @param timeout the timeout in milliseconds
172     * @return the first matching element on the current page, if found
173     * @throws NoSuchElementException when not found
174     */
175    public static WebElement findElementWithTimeout(By by) throws NoSuchElementException {
176        return Locator.findElementWithTimeout(by);
177    }
178
179    /**
180     * Finds webelement list using the given method, with a timeout
181     */
182    public static List<WebElement> findElementsWithTimeout(By by) throws NoSuchElementException {
183        return Locator.findElementsWithTimeout(by);
184    }
185
186    /**
187     * Finds the first {@link WebElement} using the given method, with a timeout.
188     *
189     * @param by the locating mechanism
190     * @param parentElement find from the element
191     * @return the first matching element on the current page, if found
192     * @throws NoSuchElementException when not found
193     */
194    public static WebElement findElementWithTimeout(By by, WebElement parentElement) throws NoSuchElementException {
195        return Locator.findElementWithTimeout(by, parentElement);
196    }
197
198    /**
199     * Waits until an element is enabled, with a timeout.
200     *
201     * @param element the element
202     */
203    public static void waitUntilEnabled(WebElement element) throws NotFoundException {
204        Locator.waitUntilEnabled(element);
205    }
206
207    /**
208     * Finds the first {@link WebElement} using the given method, with a {@code findElementTimeout}. Then waits until
209     * the element is enabled, with a {@code waitUntilEnabledTimeout}.
210     *
211     * @param by the locating mechanism
212     * @param findElementTimeout the find element timeout in milliseconds
213     * @param waitUntilEnabledTimeout the wait until enabled timeout in milliseconds
214     * @return the first matching element on the current page, if found
215     * @throws NotFoundException if the element is not found or not enabled
216     */
217    public static WebElement findElementAndWaitUntilEnabled(By by, int findElementTimeout, int waitUntilEnabledTimeout)
218            throws NotFoundException {
219        return Locator.findElementAndWaitUntilEnabled(by, findElementTimeout, waitUntilEnabledTimeout);
220    }
221
222    /**
223     * Finds the first {@link WebElement} using the given method, with the default timeout. Then waits until the element
224     * is enabled, with the default timeout.
225     *
226     * @param by the locating mechanism
227     * @return the first matching element on the current page, if found
228     * @throws NotFoundException if the element is not found or not enabled
229     */
230    public static WebElement findElementAndWaitUntilEnabled(By by) throws NotFoundException {
231        return Locator.findElementAndWaitUntilEnabled(by);
232    }
233
234    /**
235     * Finds the first {@link WebElement} using the given method, with a {@code findElementTimeout}. Then waits until
236     * the element is enabled, with a {@code waitUntilEnabledTimeout}. Then clicks on the element.
237     *
238     * @param by the locating mechanism
239     * @param findElementTimeout the find element timeout in milliseconds
240     * @param waitUntilEnabledTimeout the wait until enabled timeout in milliseconds
241     * @throws NotFoundException if the element is not found or not enabled
242     */
243    public static void findElementWaitUntilEnabledAndClick(By by, int findElementTimeout, int waitUntilEnabledTimeout)
244            throws NotFoundException {
245        Locator.waitUntilElementEnabledAndClick(by, findElementTimeout, waitUntilEnabledTimeout);
246    }
247
248    /**
249     * Finds the first {@link WebElement} using the given method, with the default timeout. Then waits until the element
250     * is enabled, with the default timeout. Then clicks on the element.
251     *
252     * @param by the locating mechanism
253     * @throws NotFoundException if the element is not found or not enabled
254     */
255    public static void findElementWaitUntilEnabledAndClick(By by) throws NotFoundException {
256        Locator.findElementWaitUntilEnabledAndClick(by);
257    }
258
259    /**
260     * Waits until the URL is different from the one given in parameter, with a timeout.
261     *
262     * @param url the URL to compare to
263     */
264    public void waitUntilURLDifferentFrom(String url) {
265        Locator.waitUntilURLDifferentFrom(url);
266    }
267
268    /**
269     * Selects item in drop down menu.
270     *
271     * @since 5.7
272     */
273    public void selectItemInDropDownMenu(WebElement selector, String optionLabel) {
274        Select select = new Select(selector);
275        select.selectByVisibleText(optionLabel);
276    }
277
278    /**
279     * Switch to given frame id.
280     *
281     * @since 5.7.3
282     */
283    public WebDriver switchToFrame(String id) {
284        driver.switchTo().defaultContent();
285        // you are now outside both frames
286        return driver.switchTo().frame(id);
287    }
288
289    /**
290     * Helper method to adapt tests behaviour when ajaxifying tabs.
291     *
292     * @since 7.10
293     */
294    public boolean useAjaxTabs() {
295        return true;
296    }
297
298    protected void clickOnTabIfNotSelected(String tabPanelId, WebElement tabElement) {
299        clickOnTabIfNotSelected(tabPanelId, tabElement, useAjaxTabs());
300    }
301
302    protected void clickOnTabIfNotSelected(String tabPanelId, WebElement tabElement, boolean useAjax) {
303        WebElement selectedTab = findElementWithTimeout(
304                By.xpath("//div[@id='" + tabPanelId + "']//li[@class='selected']//a/span"));
305        if (!selectedTab.equals(tabElement)) {
306            if (useAjax) {
307                AjaxRequestManager arm = new AjaxRequestManager(driver);
308                arm.begin();
309                tabElement.click();
310                arm.end();
311            } else {
312                tabElement.click();
313            }
314        }
315    }
316
317    protected void clickOnTabIfNotSelected(String tabPanelId, String tabElementId) {
318        WebElement tabElement = findElementWithTimeout(
319                By.xpath("//div[@id='" + tabPanelId + "']//a[contains(@id,'" + tabElementId + "')]/span"));
320        clickOnTabIfNotSelected(tabPanelId, tabElement);
321    }
322
323}