001/*
002 * (C) Copyright 2016 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 <stan@nuxeo.com>
018 *     Antoine Taillefer
019 *     Gabriel Barata
020 */
021package org.nuxeo.functionaltests.pages;
022
023import java.io.IOException;
024import java.util.List;
025import java.util.stream.Collectors;
026
027import org.apache.commons.lang.StringUtils;
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.nuxeo.functionaltests.AjaxRequestManager;
031import org.nuxeo.functionaltests.Constants;
032import org.nuxeo.functionaltests.Locator;
033import org.nuxeo.functionaltests.Required;
034import org.nuxeo.functionaltests.fragment.AddAllToCollectionForm;
035import org.nuxeo.functionaltests.fragment.AddToCollectionForm;
036import org.nuxeo.functionaltests.pages.actions.ContextualActions;
037import org.nuxeo.functionaltests.pages.admincenter.AdminCenterBasePage;
038import org.nuxeo.functionaltests.pages.forms.CollectionCreationFormPage;
039import org.nuxeo.functionaltests.pages.forms.DublinCoreCreationDocumentFormPage;
040import org.nuxeo.functionaltests.pages.forms.FileCreationFormPage;
041import org.nuxeo.functionaltests.pages.forms.FolderCreationFormPage;
042import org.nuxeo.functionaltests.pages.forms.ForumCreationFormPage;
043import org.nuxeo.functionaltests.pages.forms.NoteCreationFormPage;
044import org.nuxeo.functionaltests.pages.forms.WorkspaceCreationFormPage;
045import org.nuxeo.functionaltests.pages.search.SearchPage;
046import org.nuxeo.functionaltests.pages.tabs.CollectionContentTabSubPage;
047import org.nuxeo.functionaltests.pages.tabs.CommentsTabSubPage;
048import org.nuxeo.functionaltests.pages.tabs.ContentTabSubPage;
049import org.nuxeo.functionaltests.pages.tabs.EditTabSubPage;
050import org.nuxeo.functionaltests.pages.tabs.FilesTabSubPage;
051import org.nuxeo.functionaltests.pages.tabs.ForumTabSubPage;
052import org.nuxeo.functionaltests.pages.tabs.HistoryTabSubPage;
053import org.nuxeo.functionaltests.pages.tabs.ManageTabSubPage;
054import org.nuxeo.functionaltests.pages.tabs.PermissionsSubPage;
055import org.nuxeo.functionaltests.pages.tabs.PublishTabSubPage;
056import org.nuxeo.functionaltests.pages.tabs.RelationTabSubPage;
057import org.nuxeo.functionaltests.pages.tabs.SectionContentTabSubPage;
058import org.nuxeo.functionaltests.pages.tabs.SectionsContentTabSubPage;
059import org.nuxeo.functionaltests.pages.tabs.SummaryTabSubPage;
060import org.nuxeo.functionaltests.pages.tabs.TopicTabSubPage;
061import org.nuxeo.functionaltests.pages.tabs.WorkflowTabSubPage;
062import org.nuxeo.functionaltests.pages.tabs.WorkspacesContentTabSubPage;
063import org.nuxeo.functionaltests.pages.workspace.WorkspaceHomePage;
064import org.openqa.selenium.By;
065import org.openqa.selenium.JavascriptExecutor;
066import org.openqa.selenium.NoSuchElementException;
067import org.openqa.selenium.StaleElementReferenceException;
068import org.openqa.selenium.WebDriver;
069import org.openqa.selenium.WebElement;
070import org.openqa.selenium.support.FindBy;
071
072import static org.nuxeo.functionaltests.Constants.FILE_TYPE;
073import static org.nuxeo.functionaltests.Constants.FOLDER_TYPE;
074import static org.nuxeo.functionaltests.Constants.FORUM_TYPE;
075import static org.nuxeo.functionaltests.Constants.NOTE_TYPE;
076import static org.nuxeo.functionaltests.Constants.WORKSPACES_TITLE;
077
078import static org.junit.Assert.assertEquals;
079
080/**
081 * The nuxeo main document base page
082 *
083 * @author Sun Seng David TAN <stan@nuxeo.com>
084 */
085public class DocumentBasePage extends AbstractPage {
086
087    private static final Log log = LogFactory.getLog(DocumentBasePage.class);
088
089    /**
090     * Exception occurred a user is expected to be connected but it isn't.
091     */
092    public class UserNotConnectedException extends Exception {
093
094        private static final long serialVersionUID = 1L;
095
096        public UserNotConnectedException(String username) {
097            super("The user " + username + " is expected to be connected but isn't");
098        }
099    }
100
101    @FindBy(xpath = "//form[@id='breadcrumbForm']")
102    public WebElement breadcrumbForm;
103
104    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Content']")
105    public WebElement contentTabLink;
106
107    public ContextualActions contextualActions;
108
109    @FindBy(className = "creator")
110    public WebElement currentDocumentContributor;
111
112    @FindBy(className = "documentDescription")
113    public WebElement currentDocumentDescription;
114
115    @FindBy(xpath = "//form[@id='document_header_layout_form']//h1")
116    public WebElement currentDocumentTitle;
117
118    @FindBy(className = "currentDocumentDescription")
119    public WebElement currentFolderishDescription;
120
121    @FindBy(linkText = "WORKSPACE")
122    public WebElement documentManagementLink;
123
124    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Edit']")
125    public WebElement editTabLink;
126
127    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Files']")
128    public WebElement filesTabLink;
129
130    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Permissions']")
131    public WebElement permissionsTabLink;
132
133    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='History']")
134    public WebElement historyTabLink;
135
136    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Manage']")
137    public WebElement manageTabLink;
138
139    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Relations']")
140    public WebElement relationTabLink;
141
142    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Summary']")
143    public WebElement summaryTabLink;
144
145    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Publish']")
146    public WebElement publishTabLink;
147
148    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Comments']")
149    public WebElement commentsTabLink;
150
151    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Forum']")
152    public WebElement forumTabLink;
153
154    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Topic']")
155    public WebElement topicTabLink;
156
157    @Required
158    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']")
159    public WebElement tabsBar;
160
161    @FindBy(xpath = "//div[@id='nxw_documentTabs_panel']//a/span[text()='Workflow']")
162    public WebElement workflowLink;
163
164    @Required
165    @FindBy(id = "nxw_userMenuActions_panel")
166    public WebElement userMenuActions;
167
168    @Required
169    @FindBy(linkText = "HOME")
170    public WebElement homePageLink;
171
172    @Required
173    @FindBy(linkText = "SEARCH")
174    public WebElement searchPageLink;
175
176    public DocumentBasePage(WebDriver driver) {
177        super(driver);
178    }
179
180    /**
181     * Check if the title of the current document page is equal to the {@code expectedTitle}.
182     *
183     * @param expectedTitle the expected title
184     */
185    public void checkDocTitle(String expectedTitle) {
186        assertEquals(expectedTitle, getCurrentDocumentTitle());
187    }
188
189    /**
190     * Check if the user is connected by looking for an element with the {@code username} as a class.
191     *
192     * @param username the username
193     * @throws UserNotConnectedException
194     */
195    public void checkUserConnected(String username) throws UserNotConnectedException {
196        try {
197            findElementWithTimeout(By.cssSelector("span." + username));
198        } catch (NoSuchElementException e) {
199            throw new UserNotConnectedException(username);
200        }
201    }
202
203    /**
204     * @since 7.10
205     */
206    public void clickOnDocumentTabLink(WebElement tabLink) {
207        clickOnDocumentTabLink(tabLink, useAjaxTabs());
208    }
209
210    /**
211     * Clicks on given tab element, detecting begin and end of potential ajax request.
212     *
213     * @since 8.1
214     */
215    public void clickOnDocumentTabLink(WebElement tabLink, boolean useAjax) {
216        clickOnTabIfNotSelected("nxw_documentTabs_panel", tabLink, useAjax);
217    }
218
219    public AdminCenterBasePage getAdminCenter() {
220        findElementWaitUntilEnabledAndClick(By.linkText("ADMIN"));
221        return asPage(AdminCenterBasePage.class);
222    }
223
224    /**
225     * Click on the content tab and return the subpage of this page.
226     */
227    public ContentTabSubPage getContentTab() {
228        return getContentTab(ContentTabSubPage.class);
229    }
230
231    public <T> T getContentTab(Class<T> tabClass) {
232        clickOnDocumentTabLink(contentTabLink);
233        return asPage(tabClass);
234    }
235
236    public CollectionContentTabSubPage getCollectionContentTab() {
237        return getContentTab(CollectionContentTabSubPage.class);
238    }
239
240    public ContextualActions getContextualActions() {
241        return asPage(ContextualActions.class);
242    }
243
244    /**
245     * @since 7.3
246     */
247    public List<WebElement> getBlobActions(int index) {
248        return findElementsWithTimeout(By.xpath("(//div[@class='actionsColumn'])[" + (index + 1) + "]//a"));
249    }
250
251    public String getCurrentContributors() {
252        return currentDocumentContributor.getText();
253    }
254
255    public String getCurrentDocumentDescription() {
256        return currentDocumentDescription.getText();
257    }
258
259    public String getCurrentDocumentTitle() {
260        return currentDocumentTitle.getText();
261    }
262
263    public String getCurrentFolderishDescription() {
264        return currentFolderishDescription.getText();
265    }
266
267    public List<String> getCurrentStates() {
268        return findElementsWithTimeout(By.className("sticker")).stream()
269                                                               .map(WebElement::getText)
270                                                               .collect(Collectors.toList());
271    }
272
273    /**
274     * @deprecated since 7.3: use {@link #goToWorkspaces()} instead
275     */
276    @Deprecated
277    public DocumentBasePage getDocumentManagement() {
278        return goToWorkspaces();
279    }
280
281    public EditTabSubPage getEditTab() {
282        return getEditTab(EditTabSubPage.class);
283    }
284
285    /**
286     * @since 8.3
287     */
288    public <T extends EditTabSubPage> T getEditTab(Class<T> tabClass) {
289        clickOnDocumentTabLink(editTabLink);
290        return asPage(tabClass);
291    }
292
293    public FilesTabSubPage getFilesTab() {
294        clickOnDocumentTabLink(filesTabLink);
295        return asPage(FilesTabSubPage.class);
296    }
297
298    public PermissionsSubPage getPermissionsTab() {
299        // not ajaxified
300        clickOnDocumentTabLink(permissionsTabLink, false);
301        return asPage(PermissionsSubPage.class);
302    }
303
304    public HistoryTabSubPage getHistoryTab() {
305        clickOnDocumentTabLink(historyTabLink);
306        return asPage(HistoryTabSubPage.class);
307    }
308
309    public ManageTabSubPage getManageTab() {
310        clickOnDocumentTabLink(manageTabLink);
311        return asPage(ManageTabSubPage.class);
312    }
313
314    public NavigationSubPage getNavigationSubPage() {
315        return asPage(NavigationSubPage.class);
316    }
317
318    public RelationTabSubPage getRelationTab() {
319        clickOnDocumentTabLink(relationTabLink);
320        return asPage(RelationTabSubPage.class);
321    }
322
323    public SummaryTabSubPage getSummaryTab() {
324        clickOnDocumentTabLink(summaryTabLink);
325        return asPage(SummaryTabSubPage.class);
326    }
327
328    /**
329     * @since 8.3
330     */
331    public CommentsTabSubPage getCommentsTab() {
332        clickOnDocumentTabLink(commentsTabLink);
333        return asPage(CommentsTabSubPage.class);
334    }
335
336    /**
337     * @since 8.3
338     */
339    public ForumTabSubPage getForumTab() {
340        clickOnDocumentTabLink(forumTabLink);
341        return asPage(ForumTabSubPage.class);
342    }
343
344    /**
345     * @since 8.3
346     */
347    public TopicTabSubPage getTopicTab() {
348        clickOnDocumentTabLink(topicTabLink);
349        return asPage(TopicTabSubPage.class);
350    }
351
352    /**
353     * @since 8.3
354     */
355    public PublishTabSubPage getPublishTab() {
356        clickOnDocumentTabLink(publishTabLink);
357        return asPage(PublishTabSubPage.class);
358    }
359
360    /**
361     * @since 5.7
362     */
363    public UserHomePage getUserHome() {
364        findElementWaitUntilEnabledAndClick(By.linkText("HOME"));
365        UserHomePage page = asPage(UserHomePage.class);
366        // make sure we're back on the dashboard tab
367        return page.goToDashboard();
368    }
369
370    public WorkflowTabSubPage getWorkflow() {
371        clickOnDocumentTabLink(workflowLink);
372        return asPage(WorkflowTabSubPage.class);
373    }
374
375    /**
376     * For workspace type, the content tab is a bit different.
377     */
378    public WorkspacesContentTabSubPage getWorkspacesContentTab() {
379        clickOnDocumentTabLink(contentTabLink);
380        return asPage(WorkspacesContentTabSubPage.class);
381    }
382
383    public DocumentBasePage goToDocumentByBreadcrumb(String documentTitle) {
384        clickOnBreadcrumbElement(driver, documentTitle);
385        return asPage(DocumentBasePage.class);
386    }
387
388    /**
389     * Makes a breadcrumb element usable, to workaround issues in tests when resolution is too small, see NXP-19710.
390     *
391     * @since 8.3
392     */
393    public static void makeBreadcrumbUsable(WebDriver driver) {
394        log.warn("Removing header elements to make breadcrumb usable");
395        JavascriptExecutor executor = (JavascriptExecutor) driver;
396        // ugly hack for NXP-19710: prevent header elements from hiding breadcrumb links when window is too small
397        String[] ids = { "logolink", "nxw_mainTabs_panel", "nxw_userActions_panel", "nxw_userMenuActions_panel",
398                "nxw_headerSearch_panel" };
399        for (String id : ids) {
400            try {
401                // make sure element is loaded
402                driver.findElement(By.id(id));
403                // remove it
404                executor.executeScript("return document.getElementById('" + id + "').remove()");
405            } catch (NoSuchElementException e) {
406                // ignore
407            }
408        }
409    }
410
411    /**
412     * Clicks on a breadcrumb element.
413     *
414     * @since 8.3
415     */
416    public static void clickOnBreadcrumbElement(WebDriver driver, String documentTitle) {
417        makeBreadcrumbUsable(driver);
418        WebElement breadcrumb = driver.findElement(By.xpath("//form[@id='breadcrumbForm']"));
419        Locator.waitUntilEnabledAndClick(breadcrumb.findElement(By.linkText(documentTitle)));
420    }
421
422    private static final String ADD_TO_COLLECTION_UPPER_ACTION_ID = "nxw_addToCollectionAction_form:nxw_addToCollectionAction_link";
423
424    private static final String ADD_ALL_TO_COLLECTION_ACTION_ID = "document_content_buttons:nxw_addSelectedToCollectionAction_form:nxw_addSelectedToCollectionAction_link";
425
426    @FindBy(id = ADD_TO_COLLECTION_UPPER_ACTION_ID)
427    private WebElement addToCollectionUpperAction;
428
429    @FindBy(id = ADD_ALL_TO_COLLECTION_ACTION_ID)
430    private WebElement addAllToCollectionAction;
431
432    /**
433     * @since 5.9.3
434     */
435    public AddToCollectionForm getAddToCollectionPopup() {
436        AjaxRequestManager arm = new AjaxRequestManager(driver);
437        arm.begin();
438        waitUntilEnabledAndClick(addToCollectionUpperAction);
439        arm.end();
440        WebElement elt = AbstractPage.getFancyBoxContent();
441        return getWebFragment(elt, AddToCollectionForm.class);
442    }
443
444    /**
445     * @since 5.9.3
446     */
447    public AddAllToCollectionForm getAddAllToCollectionPopup() {
448        Locator.waitUntilGivenFunctionIgnoring(
449                driver -> StringUtils.isBlank(
450                        driver.findElement(By.id(ADD_ALL_TO_COLLECTION_ACTION_ID)).getAttribute("disabled")),
451                StaleElementReferenceException.class);
452        AjaxRequestManager arm = new AjaxRequestManager(driver);
453        arm.begin();
454        findElementWaitUntilEnabledAndClick(By.id(ADD_ALL_TO_COLLECTION_ACTION_ID));
455        arm.end();
456        WebElement elt = AbstractPage.getFancyBoxContent();
457        return getWebFragment(elt, AddAllToCollectionForm.class);
458    }
459
460    public boolean isAddToCollectionUpperActionAvailable() {
461        try {
462            driver.findElement(By.id(ADD_TO_COLLECTION_UPPER_ACTION_ID));
463            return true;
464        } catch (final NoSuchElementException e) {
465            return false;
466        }
467    }
468
469    /**
470     * @since 5.9.3
471     */
472    public void popupUserMenuActions() {
473        Locator.findElementWaitUntilEnabledAndClick(userMenuActions, By.id("nxw_userMenuActions_dropDownMenu"));
474        Locator.waitUntilGivenFunctionIgnoring(
475                driver -> !userMenuActions.findElement(By.xpath("//ul[@class='actionSubList']"))
476                                          .getAttribute("style")
477                                          .equals("display: none;"),
478                StaleElementReferenceException.class);
479    }
480
481    /**
482     * @since 5.9.3
483     */
484    public DocumentBasePage switchToPersonalWorkspace() {
485        popupUserMenuActions();
486        findElementWaitUntilEnabledAndClick(By.linkText("Personal Workspace"));
487        return asPage(DocumentBasePage.class);
488    }
489
490    /**
491     * @since 5.9.3
492     */
493    public DocumentBasePage switchToDocumentBase() {
494        popupUserMenuActions();
495        findElementWaitUntilEnabledAndClick(By.linkText("Back to Document Base"));
496        return asPage(DocumentBasePage.class);
497    }
498
499    /**
500     * @since 5.9.3
501     */
502    public HomePage goToHomePage() {
503        waitUntilEnabledAndClick(homePageLink);
504        return asPage(HomePage.class);
505    }
506
507    /**
508     * @since 6.0
509     */
510    public SearchPage goToSearchPage() {
511        waitUntilEnabledAndClick(searchPageLink);
512        return asPage(SearchPage.class);
513    }
514
515    /**
516     * @since 7.3
517     */
518    public WorkspaceHomePage goToWorkspaces() {
519        waitUntilEnabledAndClick(documentManagementLink);
520        return asPage(WorkspaceHomePage.class);
521    }
522
523    /**
524     * Returns true if given element representing a main tab is selected in UI.
525     *
526     * @since 7.3
527     */
528    public boolean isMainTabSelected(WebElement tab) {
529        WebElement elt = Locator.findParentTag(tab, "li");
530        String css = elt.getAttribute("class");
531        return css != null && css.contains("selected");
532    }
533
534    /**
535     * Creates a Workspace from this page.
536     *
537     * @param workspaceTitle the workspace title
538     * @param workspaceDescription the workspace description
539     * @return the created Workspace page
540     * @since 8.3
541     */
542    public DocumentBasePage createWorkspace(String workspaceTitle, String workspaceDescription) {
543        // Go to Workspaces
544        DocumentBasePage workspacesPage = getNavigationSubPage().goToDocument(WORKSPACES_TITLE);
545        // Get Workspace creation form page
546        WorkspaceCreationFormPage workspaceCreationFormPage = workspacesPage.getWorkspacesContentTab()
547                                                                            .getWorkspaceCreatePage();
548        // Create Workspace
549        DocumentBasePage workspacePage = workspaceCreationFormPage.createNewWorkspace(workspaceTitle,
550                workspaceDescription);
551        return workspacePage;
552    }
553
554    /**
555     * Creates a Section from this page.
556     *
557     * @param sectionTitle the section title
558     * @param sectionDescription the section description
559     * @return the created Section page
560     * @since 8.3
561     */
562    public DocumentBasePage createSection(String sectionTitle, String sectionDescription) {
563        getNavigationSubPage().goToDocument(Constants.SECTIONS_TITLE);
564        DublinCoreCreationDocumentFormPage sectionCreationPage = asPage(
565                SectionsContentTabSubPage.class).getSectionCreatePage();
566        return sectionCreationPage.createDocument(sectionTitle, sectionDescription);
567    }
568
569    /**
570     * Deletes the Workspace with title {@code workspaceTitle} from this page.
571     *
572     * @param workspaceTitle the workspace title
573     * @since 8.3
574     */
575    public void deleteWorkspace(String workspaceTitle) {
576        // Go to Workspaces
577        DocumentBasePage workspacesPage = getNavigationSubPage().goToDocument(WORKSPACES_TITLE);
578        // Delete the Workspace
579        workspacesPage.getContentTab().removeDocument(workspaceTitle);
580    }
581
582    /**
583     * @since 8.3
584     */
585    public FolderDocumentBasePage createFolder(String folderTitle, String folderDescription) {
586        // Get Folder creation form page
587        FolderCreationFormPage folderCreationFormPage = getContentTab().getDocumentCreatePage(FOLDER_TYPE,
588                FolderCreationFormPage.class);
589        // Create Folder
590        FolderDocumentBasePage folderPage = folderCreationFormPage.createFolderDocument(folderTitle, folderDescription);
591        return folderPage;
592    }
593
594    /**
595     * Creates a File from this page.
596     *
597     * @param fileTitle the file title
598     * @param fileDescription the file description
599     * @param uploadBlob true if a blob needs to be uploaded (temporary file created for this purpose)
600     * @param filePrefix the file prefix
601     * @param fileSuffix the file suffix
602     * @param fileContent the file content
603     * @return the created File page
604     * @throws IOException if temporary file creation fails
605     * @since 8.3
606     */
607    public FileDocumentBasePage createFile(String fileTitle, String fileDescription, boolean uploadBlob,
608            String filePrefix, String fileSuffix, String fileContent) throws IOException {
609        // Get File creation form page
610        FileCreationFormPage fileCreationFormPage = getContentTab().getDocumentCreatePage(FILE_TYPE,
611                FileCreationFormPage.class);
612        // Create File
613        FileDocumentBasePage filePage = fileCreationFormPage.createFileDocument(fileTitle, fileDescription, uploadBlob,
614                filePrefix, fileSuffix, fileDescription);
615        return filePage;
616    }
617
618    /**
619     * Creates a Collections container from this page.
620     *
621     * @param collectionsTitle the Collections container title
622     * @param fileDescription the collections description
623     * @return the created Collections page
624     * @since 8.3
625     */
626    public DocumentBasePage createCollections(String collectionsTitle, String fileDescription) {
627        DublinCoreCreationDocumentFormPage dublinCoreDocumentFormPage = getContentTab().getDocumentCreatePage(
628                "Collections", DublinCoreCreationDocumentFormPage.class);
629        // Create File
630        DocumentBasePage documentBasePage = dublinCoreDocumentFormPage.createDocument(collectionsTitle,
631                fileDescription);
632        return documentBasePage;
633    }
634
635    /**
636     * Creates a Collection from this page.
637     *
638     * @param collectionsTitle the Collections container title
639     * @param fileDescription the collection description
640     * @return the created Collections page
641     * @since 8.3
642     */
643    public CollectionContentTabSubPage createCollection(String collectionsTitle, String fileDescription) {
644        CollectionCreationFormPage collectionCreationFormPage = getContentTab().getDocumentCreatePage("Collection",
645                CollectionCreationFormPage.class);
646        // Create File
647        CollectionContentTabSubPage documentBasePage = collectionCreationFormPage.createDocument(collectionsTitle,
648                fileDescription);
649        return documentBasePage;
650    }
651
652    /**
653     * Creates a Note from this page.
654     *
655     * @param noteTitle the note title
656     * @param noteDescription the note description
657     * @param defineNote true if the content of the note needs to be defined
658     * @param noteContent the content of the note
659     * @return the created note page.
660     * @throws IOException
661     * @since 8.3
662     */
663    public NoteDocumentBasePage createNote(String noteTitle, String noteDescription, boolean defineNote,
664            String noteContent) throws IOException {
665        // Get the Note creation form
666        NoteCreationFormPage noteCreationPage = getContentTab().getDocumentCreatePage(NOTE_TYPE,
667                NoteCreationFormPage.class);
668        // Create a Note
669        NoteDocumentBasePage notePage = noteCreationPage.createNoteDocument(noteTitle, noteDescription, defineNote,
670                noteContent);
671        return notePage;
672    }
673
674    /**
675     * Creates a forum on this page.
676     *
677     * @param forumTitle the forum title
678     * @param forumDescription the forum description
679     * @return the created forum page
680     * @since 8.3
681     */
682    public ForumTabSubPage createForum(String forumTitle, String forumDescription) {
683        // Get a Forum creation form
684        ForumCreationFormPage forumCreationFormPage = getContentTab().getDocumentCreatePage(FORUM_TYPE,
685                ForumCreationFormPage.class);
686        // Create a Forum
687        ForumTabSubPage forumPage = forumCreationFormPage.createForumDocument(forumTitle, forumDescription);
688        return forumPage;
689    }
690
691    /**
692     * @since 8.3
693     */
694    public boolean hasNewRelationLink() {
695        return getRelationTab().hasNewRelationLink();
696    }
697
698    /**
699     * @since 8.3
700     */
701    public boolean hasFilesTab() {
702        try {
703            return getFilesTab() != null;
704        } catch (NoSuchElementException e) {
705            return false;
706        }
707    }
708
709    /**
710     * @since 8.3
711     */
712    public boolean hasNewButton(boolean isSection) {
713        if (isSection) {
714            return getContentTab(SectionContentTabSubPage.class).hasNewButton();
715        }
716        return getContentTab().hasNewButton();
717    }
718
719    /**
720     * @since 8.3
721     */
722    public boolean hasEditTab() {
723        try {
724            return getEditTab() != null;
725        } catch (NoSuchElementException e) {
726            return false;
727        }
728    }
729
730    /**
731     * @since 8.3
732     */
733    public boolean hasNewPermissionsButton() {
734        return getPermissionsTab().hasNewPermissionButton();
735    }
736
737    /**
738     * @since 8.3
739     */
740    public boolean hasManageTab() {
741        try {
742            return getManageTab() != null;
743        } catch (NoSuchElementException e) {
744            return false;
745        }
746    }
747
748}