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