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