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 <stan@nuxeo.com>
016 *     Antoine Taillefer
017 */
018package org.nuxeo.functionaltests.pages;
019
020import java.util.ArrayList;
021import java.util.List;
022
023import org.apache.commons.lang.StringUtils;
024import org.nuxeo.functionaltests.Locator;
025import org.nuxeo.functionaltests.Required;
026import org.nuxeo.functionaltests.fragment.AddToCollectionForm;
027import org.nuxeo.functionaltests.pages.actions.ContextualActions;
028import org.nuxeo.functionaltests.pages.admincenter.AdminCenterBasePage;
029import org.nuxeo.functionaltests.pages.search.SearchPage;
030import org.nuxeo.functionaltests.pages.tabs.CollectionContentTabSubPage;
031import org.nuxeo.functionaltests.pages.tabs.ContentTabSubPage;
032import org.nuxeo.functionaltests.pages.tabs.EditTabSubPage;
033import org.nuxeo.functionaltests.pages.tabs.HistoryTabSubPage;
034import org.nuxeo.functionaltests.pages.tabs.ManageTabSubPage;
035import org.nuxeo.functionaltests.pages.tabs.RelationTabSubPage;
036import org.nuxeo.functionaltests.pages.tabs.SummaryTabSubPage;
037import org.nuxeo.functionaltests.pages.tabs.WorkflowTabSubPage;
038import org.nuxeo.functionaltests.pages.tabs.WorkspacesContentTabSubPage;
039import org.openqa.selenium.By;
040import org.openqa.selenium.NoSuchElementException;
041import org.openqa.selenium.StaleElementReferenceException;
042import org.openqa.selenium.WebDriver;
043import org.openqa.selenium.WebElement;
044import org.openqa.selenium.support.FindBy;
045
046import com.google.common.base.Function;
047
048import static org.junit.Assert.assertEquals;
049
050/**
051 * The nuxeo main document base page
052 *
053 * @author Sun Seng David TAN <stan@nuxeo.com>
054 */
055public class DocumentBasePage extends AbstractPage {
056
057    /**
058     * Exception occurred a user is expected to be connected but it isn't.
059     */
060    public class UserNotConnectedException extends Exception {
061        /**
062         *
063         */
064        private static final long serialVersionUID = 1L;
065
066        public UserNotConnectedException(String username) {
067            super("The user " + username + " is expected to be connected but isn't");
068        }
069    }
070
071    @FindBy(xpath = "//form[@id='breadcrumbForm']")
072    public WebElement breadcrumbForm;
073
074    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Content']")
075    public WebElement contentTabLink;
076
077    public ContextualActions contextualActions;
078
079    @FindBy(className = "creator")
080    public WebElement currentDocumentContributor;
081
082    @FindBy(className = "documentDescription")
083    public WebElement currentDocumentDescription;
084
085    @FindBy(xpath = "//form[@id='document_header_layout_form']//h1")
086    public WebElement currentDocumentTitle;
087
088    @FindBy(className = "currentDocumentDescription")
089    public WebElement currentFolderishDescription;
090
091    @FindBy(linkText = "WORKSPACE")
092    public WebElement documentManagementLink;
093
094    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Edit']")
095    public WebElement editTabLink;
096
097    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='History']")
098    public WebElement historyTabLink;
099
100    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Manage']")
101    public WebElement manageTabLink;
102
103    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Relations']")
104    public WebElement relationTabLink;
105
106    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Summary']")
107    public WebElement summaryTabLink;
108
109    @Required
110    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']")
111    public WebElement tabsBar;
112
113    @FindBy(linkText = "Workflow")
114    public WebElement workflowLink;
115
116    @Required
117    @FindBy(id = "nxw_userMenuActions_panel")
118    public WebElement userMenuActions;
119
120    @Required
121    @FindBy(linkText = "HOME")
122    public WebElement homePageLink;
123
124    @Required
125    @FindBy(linkText = "SEARCH")
126    public WebElement searchPageLink;
127
128    public DocumentBasePage(WebDriver driver) {
129        super(driver);
130    }
131
132    /**
133     * Check if the title of the current document page is equal to the {@code expectedTitle}.
134     *
135     * @param expectedTitle the expected title
136     */
137    public void checkDocTitle(String expectedTitle) {
138        assertEquals(expectedTitle, getCurrentDocumentTitle());
139    }
140
141    /**
142     * Check if the user is connected by looking for the text: You are logged as Username
143     *
144     * @param username
145     * @throws UserNotConnectedException
146     */
147    public void checkUserConnected(String username) throws UserNotConnectedException {
148        if (!(getHeaderLinks().getText().contains(username))) {
149            throw new UserNotConnectedException(username);
150        }
151    }
152
153    protected void clickOnLinkIfNotSelected(WebElement tabLink) {
154        WebElement selectedTab = findElementWithTimeout(By.xpath("//div[@id='nxw_documentTabs_panel']//li[@class='selected']/a/span"));
155        if (!selectedTab.equals(tabLink)) {
156            tabLink.click();
157        }
158    }
159
160    public AdminCenterBasePage getAdminCenter() {
161        findElementWithTimeout(By.linkText("ADMIN")).click();
162        return asPage(AdminCenterBasePage.class);
163    }
164
165    /**
166     * Click on the content tab and return the subpage of this page.
167     */
168    public ContentTabSubPage getContentTab() {
169        return getContentTab(ContentTabSubPage.class);
170    }
171
172    public <T extends ContentTabSubPage> T getContentTab(Class<T> tabClass) {
173        clickOnLinkIfNotSelected(contentTabLink);
174        return asPage(tabClass);
175    }
176
177    public CollectionContentTabSubPage getCollectionContentTab() {
178        return getContentTab(CollectionContentTabSubPage.class);
179    }
180
181    public ContextualActions getContextualActions() {
182        return asPage(ContextualActions.class);
183    }
184
185    /**
186     * @since 7.3
187     */
188    public List<WebElement> getBlobActions(int index) {
189        return findElementsWithTimeout(By.xpath("(//div[@class='actionsColumn'])[" + (index + 1) + "]//a"));
190    }
191
192    public String getCurrentContributors() {
193        return currentDocumentContributor.getText();
194    }
195
196    public String getCurrentDocumentDescription() {
197        return currentDocumentDescription.getText();
198    }
199
200    public String getCurrentDocumentTitle() {
201        return currentDocumentTitle.getText();
202    }
203
204    public String getCurrentFolderishDescription() {
205        return currentFolderishDescription.getText();
206    }
207
208    public List<String> getCurrentStates() {
209        List<WebElement> states = findElementsWithTimeout(By.className("sticker"));
210        List<String> stateLabels = new ArrayList<String>();
211        for (WebElement state : states) {
212            stateLabels.add(state.getText());
213        }
214        return stateLabels;
215    }
216
217    /**
218     * @deprecated since 7.3: use {@link #goToWorkspaces()} instead
219     */
220    public DocumentBasePage getDocumentManagement() {
221        return goToWorkspaces();
222    }
223
224    public EditTabSubPage getEditTab() {
225        clickOnLinkIfNotSelected(editTabLink);
226        return asPage(EditTabSubPage.class);
227    }
228
229    public HistoryTabSubPage getHistoryTab() {
230        clickOnLinkIfNotSelected(historyTabLink);
231        return asPage(HistoryTabSubPage.class);
232    }
233
234    public ManageTabSubPage getManageTab() {
235        clickOnLinkIfNotSelected(manageTabLink);
236        return asPage(ManageTabSubPage.class);
237    }
238
239    public NavigationSubPage getNavigationSubPage() {
240        return asPage(NavigationSubPage.class);
241    }
242
243    public RelationTabSubPage getRelationTab() {
244        clickOnLinkIfNotSelected(relationTabLink);
245        return asPage(RelationTabSubPage.class);
246    }
247
248    public SummaryTabSubPage getSummaryTab() {
249        clickOnLinkIfNotSelected(summaryTabLink);
250        return asPage(SummaryTabSubPage.class);
251    }
252
253    /**
254     * @since 5.7
255     */
256    public UserHomePage getUserHome() {
257        findElementWithTimeout(By.linkText("HOME")).click();
258        UserHomePage page = asPage(UserHomePage.class);
259        // make sure we're back on the dashboard tab
260        return page.goToDashboard();
261    }
262
263    public WorkflowTabSubPage getWorkflow() {
264        workflowLink.click();
265        return asPage(WorkflowTabSubPage.class);
266    }
267
268    /**
269     * For workspace type, the content tab is a bit different.
270     */
271    public WorkspacesContentTabSubPage getWorkspacesContentTab() {
272        clickOnLinkIfNotSelected(contentTabLink);
273        return asPage(WorkspacesContentTabSubPage.class);
274    }
275
276    public DocumentBasePage goToDocumentByBreadcrumb(String documentTitle) {
277        breadcrumbForm.findElement(By.linkText(documentTitle)).click();
278        return asPage(DocumentBasePage.class);
279    }
280
281    private static final String ADD_TO_COLLECTION_UPPER_ACTION_ID = "nxw_addToCollectionAction_form:nxw_documentActionsUpperButtons_addToCollectionAction_subview:nxw_documentActionsUpperButtons_addToCollectionAction_link";
282
283    private static final String ADD_ALL_TO_COLLECTION_ACTION_ID = "document_content_buttons:nxw_addSelectedToCollectionAction_form:nxw_cvButton_addSelectedToCollectionAction_subview:nxw_cvButton_addSelectedToCollectionAction_link";
284
285    @FindBy(id = ADD_TO_COLLECTION_UPPER_ACTION_ID)
286    private WebElement addToCollectionUpperAction;
287
288    @FindBy(id = ADD_ALL_TO_COLLECTION_ACTION_ID)
289    private WebElement addAllToCollectionAction;
290
291    /**
292     * @since 5.9.3
293     */
294    public AddToCollectionForm getAddToCollectionPopup() {
295        addToCollectionUpperAction.click();
296        Locator.waitUntilElementPresent(By.id("fancybox-content"));
297        return getWebFragment(By.id("fancybox-content"), AddToCollectionForm.class);
298    }
299
300    /**
301     * @since 5.9.3
302     */
303    public AddToCollectionForm getAddAllToCollectionPopup() {
304        Locator.waitUntilGivenFunctionIgnoring(new Function<WebDriver, Boolean>() {
305            @Override
306            public Boolean apply(WebDriver driver) {
307                return StringUtils.isBlank(driver.findElement(By.id(ADD_ALL_TO_COLLECTION_ACTION_ID)).getAttribute(
308                        "disabled"));
309            }
310        }, StaleElementReferenceException.class);
311        driver.findElement(By.id(ADD_ALL_TO_COLLECTION_ACTION_ID)).click();
312        Locator.waitUntilElementPresent(By.id("fancybox-content"));
313        return getWebFragment(By.id("fancybox-content"), AddToCollectionForm.class);
314    }
315
316    public boolean isAddToCollectionUpperActionAvailable() {
317        try {
318            driver.findElement(By.id(ADD_TO_COLLECTION_UPPER_ACTION_ID));
319            return true;
320        } catch (final NoSuchElementException e) {
321            return false;
322        }
323    }
324
325    /**
326     * @since 5.9.3
327     */
328    public void popupUserMenuActions() {
329        userMenuActions.findElement(By.id("nxw_userMenuActions_dropDownMenu")).click();
330        Locator.waitUntilGivenFunctionIgnoring(new Function<WebDriver, Boolean>() {
331            @Override
332            public Boolean apply(WebDriver driver) {
333                return !userMenuActions.findElement(By.xpath("//ul[@class='actionSubList']")).getAttribute("style").equals(
334                        "display: none;");
335            }
336        }, StaleElementReferenceException.class);
337    }
338
339    /**
340     * @since 5.9.3
341     */
342    public DocumentBasePage switchToPersonalWorkspace() {
343        popupUserMenuActions();
344        driver.findElement(By.linkText("Personal Workspace")).click();
345        return asPage(DocumentBasePage.class);
346    }
347
348    /**
349     * @since 5.9.3
350     */
351    public DocumentBasePage switchToDocumentBase() {
352        popupUserMenuActions();
353        driver.findElement(By.linkText("Back to Document Base")).click();
354        return asPage(DocumentBasePage.class);
355    }
356
357    /**
358     * @since 5.9.3
359     */
360    public HomePage goToHomePage() {
361        homePageLink.click();
362        return asPage(HomePage.class);
363    }
364
365    /**
366     * @since 6.0
367     */
368    public SearchPage goToSearchPage() {
369        searchPageLink.click();
370        return asPage(SearchPage.class);
371    }
372
373    /**
374     * @since 7.3
375     */
376    public DocumentBasePage goToWorkspaces() {
377        documentManagementLink.click();
378        return asPage(DocumentBasePage.class);
379    }
380
381    /**
382     * Returns true if given element representing a main tab is selected in UI.
383     *
384     * @since 7.3
385     */
386    public boolean isMainTabSelected(WebElement tab) {
387        WebElement elt = Locator.findParentTag(tab, "li");
388        String css = elt.getAttribute("class");
389        if (css != null && css.contains("selected")) {
390            return true;
391        }
392        return false;
393    }
394
395}