/*
* (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Nelson Silva
*/
package org.nuxeo.functionaltests.contentView;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.function.Function;
import org.nuxeo.functionaltests.AbstractTest;
import org.nuxeo.functionaltests.AjaxRequestManager;
import org.nuxeo.functionaltests.Assert;
import org.nuxeo.functionaltests.Locator;
import org.nuxeo.functionaltests.fragment.WebFragmentImpl;
import org.nuxeo.functionaltests.pages.DocumentBasePage;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
/**
* Represents a content view element.
*
* @since 7.1
*/
public class ContentViewElement extends WebFragmentImpl {
private static final String SELECT_ALL_BUTTON_XPATH = "//input[@type=\"checkbox\" and @title=\"Select all / deselect all\"]";
private static final String CHECK_BOX_XPATH = "td/input[@type=\"checkbox\"]";
public enum ResultLayout {
THUMBNAIL("Thumbnail view"), LISTING("List view");
private final String title;
ResultLayout(String title) {
this.title = title;
}
}
public ContentViewElement(WebDriver driver, WebElement element) {
super(driver, element);
}
protected ContentViewElement reload(String id) {
return getWebFragment(By.id(id), ContentViewElement.class);
}
/**
* @since 9.1
*/
public ContentViewUpperActions getUpperActions() {
return AbstractTest.getWebFragment(By.className("contentViewUpperActions"), ContentViewUpperActions.class);
}
/**
* @since 9.1
*/
public ContentViewSelectionActions getSelectionActions() {
By buttonsId = By.id(String.format("%s_buttons:ajax_selection_buttons", getContentViewType()));
Locator.waitUntilElementPresent(buttonsId);
return AbstractTest.getWebFragment(buttonsId, ContentViewSelectionActions.class);
}
public PageNavigationControls getPaginationControls() {
return AbstractTest.getWebFragment(findElement(By.className("pageNavigationControls")),
PageNavigationControls.class);
}
/**
* @since 9.1
*/
protected WebElement getFilterInput() {
String id = getContentViewId() + "_quickFilterForm:nxl_document_content_filter:nxw_search_title";
return findElement(By.id(id));
}
/**
* @since 9.1
*/
protected WebElement getFilterButton() {
String id = getContentViewId() + "_quickFilterForm:submitFilter";
return findElement(By.id(id));
}
/**
* @since 9.1
*/
protected WebElement getClearFilterButton() {
String id = getContentViewId() + "_resetFilterForm:resetFilter";
return findElement(By.id(id));
}
protected String getContentViewId() {
String id = getId();
if (id.endsWith("_panel")) {
return id.substring(0, id.length() - "_panel".length());
}
return id;
}
/**
* @return the content view id with cv_* and _\d* removed. This is useful to get the selection actions.
*/
protected String getContentViewType() {
return getContentViewId().replaceFirst("^cv_", "").replaceFirst("_\\d*$", "");
}
protected WebElement getResultsPanel() {
String id = getContentViewId() + "_resultsPanel";
return getElement().findElement(By.id(id));
}
public WebElement getActionByTitle(String title) {
return getUpperActions().getActionByTitle(title);
}
public ContentViewElement switchToResultLayout(ResultLayout layout) {
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
getUpperActions().clickOnActionByTitle(layout.title);
return reload(id);
}
/**
* Use this method to do navigation actions with reloading of this {@link ContentViewElement}.
*
* @return the new content view element
* @since 9.1
*/
public <T extends DocumentBasePage> ContentViewElement navigation(Function<PageNavigationControls, T> nav) {
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
nav.apply(getPaginationControls());
return reload(id);
}
/**
* @since 8.3
*/
public List<WebElement> getItems() {
ResultLayout layout = getResultLayout();
switch (layout) {
case THUMBNAIL:
return getResultsPanel().findElements(By.xpath(".//div[contains(@class,'bubbleBox')]"));
case LISTING:
default:
return getResultsPanel().findElements(By.xpath("(.//form)[1]//tbody//tr"));
}
}
/**
* @since 9.1
*/
public WebElement getItemWithTitleAndVersion(String title, String version) {
for (WebElement item : getItems()) {
String t = item.findElement(By.xpath("td[3]")).getText(); // title
String v = item.findElement(By.xpath("td[7]")).getText(); // version
if (t.equals(title) && v.equals(version)) {
return item;
}
}
throw new NoSuchElementException("No item with title \"" + title + "\" and version " + version);
}
/**
* @since 8.3
*/
public void clickOnItemTitle(String title) {
Locator.findElementWaitUntilEnabledAndClick(getResultsPanel(), By.linkText(title));
}
/**
* @since 9.1
*/
public void clickOnItemTitleAndVersion(String title, String version) {
if (getResultLayout() == ResultLayout.THUMBNAIL) {
throw new NoSuchElementException("Click on title and version doesn\"t work with thumbnails.");
}
WebElement item = getItemWithTitleAndVersion(title, version);
Locator.findElementWaitUntilEnabledAndClick(item, By.linkText(title));
}
/**
* @since 9.1
*/
public void clickOnItemIndex(int index) {
if (getResultLayout() == ResultLayout.THUMBNAIL) {
throw new NoSuchElementException("Click on index doesn\"t work with thumbnails.");
}
Locator.waitUntilEnabledAndClick(getItems().get(index).findElement(By.xpath("td[3]/div/a[1]")));
}
/**
* @since 8.3
*/
public boolean hasItem(String title) {
try {
WebElement element = getResultsPanel().findElement(By.linkText(title));
return element != null;
} catch (NoSuchElementException e) {
return false;
}
}
/**
* Perform filter on the given string.
*
* @param filter the string to filter
* @since 9.1
*/
public ContentViewElement filterDocument(String filter) {
WebElement filterInput = getFilterInput();
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
filterInput.clear();
filterInput.sendKeys(filter);
AjaxRequestManager arm = new AjaxRequestManager(driver);
arm.begin();
getFilterButton().click();
arm.end();
Locator.waitUntilElementPresent(By.id(getClearFilterButton().getAttribute("id")));
return reload(id);
}
/**
* Clear the current filter and refresh content view.
*
* @since 9.1
*/
public ContentViewElement clearFilter() {
WebElement clearFilterButton = getClearFilterButton();
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
String clearFilterButtonId = clearFilterButton.getAttribute("id");
AjaxRequestManager arm = new AjaxRequestManager(driver);
arm.begin();
Locator.waitUntilEnabledAndClick(clearFilterButton);
arm.end();
Locator.waitUntilElementNotPresent(By.id(clearFilterButtonId));
return reload(id);
}
/**
* @since 8.3
* @deprecated since 9.1 use {@link #selectByTitle(String...)} instead.
*/
@Deprecated
public ContentViewElement checkByTitle(String... titles) {
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
List<WebElement> items = getItems();
for (WebElement item : items) {
for (String title : titles) {
try {
item.findElement(By.linkText(title));
AjaxRequestManager arm = new AjaxRequestManager(driver);
arm.begin();
Locator.findElementWaitUntilEnabledAndClick(item, By.xpath(CHECK_BOX_XPATH));
arm.end();
break;
} catch (NoSuchElementException e) {
// next
}
}
}
return reload(id);
}
/**
* @since 9.1
*/
public ContentViewSelectionActions selectByTitle(String... titles) {
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
List<WebElement> items = getItems();
for (WebElement item : items) {
for (String title : titles) {
try {
item.findElement(By.linkText(title));
AjaxRequestManager arm = new AjaxRequestManager(driver);
arm.begin();
WebElement element = item.findElement(By.xpath(CHECK_BOX_XPATH));
assertFalse("Element with title=" + title + " is already selected", element.isSelected());
Locator.scrollAndForceClick(element);
arm.end();
break;
} catch (NoSuchElementException e) {
// next
}
}
}
return reload(id).getSelectionActions();
}
/**
* @since 9.1
*/
public ContentViewElement unselectByTitle(String... titles) {
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
List<WebElement> items = getItems();
for (WebElement item : items) {
for (String title : titles) {
try {
item.findElement(By.linkText(title));
AjaxRequestManager arm = new AjaxRequestManager(driver);
arm.begin();
WebElement element = item.findElement(By.xpath(CHECK_BOX_XPATH));
assertTrue("Element with title=" + title + " is not selected", element.isSelected());
Locator.scrollAndForceClick(element);
arm.end();
break;
} catch (NoSuchElementException e) {
// next
}
}
}
return reload(id);
}
/**
* @since 8.3
* @deprecated since 9.1 use {@link #selectByIndex(int...)}/{@link #unselectByIndex(int...)} instead.
*/
@Deprecated
public ContentViewElement checkByIndex(int... indexes) {
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
AjaxRequestManager arm = new AjaxRequestManager(driver);
for (int i : indexes) {
arm.watchAjaxRequests();
getItems().get(i).findElement(By.xpath(CHECK_BOX_XPATH)).click();
arm.waitForAjaxRequests();
}
return reload(id);
}
/**
* @since 9.1
*/
public ContentViewSelectionActions selectByIndex(int... indexes) {
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
AjaxRequestManager arm = new AjaxRequestManager(driver);
for (int i : indexes) {
arm.watchAjaxRequests();
WebElement element = getItems().get(i).findElement(By.xpath(CHECK_BOX_XPATH));
assertFalse("Element with id=" + i + " is already selected", element.isSelected());
Locator.scrollAndForceClick(element);
arm.waitForAjaxRequests();
}
return reload(id).getSelectionActions();
}
/**
* @since 9.1
*/
public ContentViewElement unselectByIndex(int... indexes) {
// get id before element is detached from DOM (during next ajax calls)
String id = getId();
AjaxRequestManager arm = new AjaxRequestManager(driver);
for (int i : indexes) {
arm.watchAjaxRequests();
WebElement element = getItems().get(i).findElement(By.xpath(CHECK_BOX_XPATH));
assertTrue("Element with id=" + i + " is not selected", element.isSelected());
Locator.scrollAndForceClick(element);
arm.waitForAjaxRequests();
}
return reload(id);
}
/**
* @since 8.3
* @deprecated since 9.1 use {@link #selectAll()}/{@link #unselectAll()} instead.
*/
@Deprecated
public ContentViewElement checkAllItems() {
WebElement selectAll = null;
try {
selectAll = getResultsPanel().findElement(By.xpath(SELECT_ALL_BUTTON_XPATH));
} catch (NoSuchElementException e) {
// no item
}
if (selectAll != null) {
// get id before element is detached from DOM (during next ajax call)
String id = getId();
AjaxRequestManager arm = new AjaxRequestManager(driver);
arm.begin();
Locator.scrollAndForceClick(selectAll);
arm.end();
return reload(id);
}
return this;
}
/**
* @since 9.1
*/
public ContentViewSelectionActions selectAll() {
WebElement selectAll = getResultsPanel().findElement(By.xpath(SELECT_ALL_BUTTON_XPATH));
assertFalse("Select all Element is already selected", selectAll.isSelected());
// get id before element is detached from DOM (during next ajax call)
String id = getId();
AjaxRequestManager arm = new AjaxRequestManager(driver);
arm.begin();
Locator.scrollAndForceClick(selectAll);
arm.end();
return reload(id).getSelectionActions();
}
/**
* CAUTION You can call this method only after a {@link #selectAll()}.
*
* @since 9.1
*/
public ContentViewElement unselectAll() {
WebElement selectAll = getResultsPanel().findElement(By.xpath(SELECT_ALL_BUTTON_XPATH));
assertTrue("Select all Element is not selected", selectAll.isSelected());
// get id before element is detached from DOM (during next ajax call)
String id = getId();
AjaxRequestManager arm = new AjaxRequestManager(driver);
arm.begin();
Locator.scrollAndForceClick(selectAll);
arm.end();
return reload(id);
}
/**
* @since 8.3
* @deprecated since 9.1 use {@link #getUpperActions()} then
* {@link ContentViewUpperActions#getActionByTitle(String)} instead. Or use select methods directly.
*/
@Deprecated
public WebElement getSelectionActionByTitle(String title) {
return getUpperActions().getActionByTitle(title);
}
/**
* @since 8.4
*/
public ResultLayout getResultLayout() {
WebElement element = getElement();
WebElement resultsPanel = getResultsPanel();
String resultLayoutSelected = ".//span[@class=\"resultLayoutSelection selected\"]/*/img[@alt=\"%s\"]";
if (Assert.hasChild(element, By.xpath(String.format(resultLayoutSelected, ResultLayout.THUMBNAIL.title)))
|| Assert.hasChild(resultsPanel, By.xpath(".//div[contains(@class,'bubbleBox')]"))) {
return ResultLayout.THUMBNAIL;
} else if (Assert.hasChild(element, By.xpath(String.format(resultLayoutSelected, ResultLayout.LISTING.title)))
|| Assert.hasChild(resultsPanel, By.xpath(".//table[@class='dataOutput']"))) {
return ResultLayout.LISTING;
}
throw new IllegalStateException("Content view is not listing nor thumbnail.");
}
}