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