/*
* Copyright 2016 Hewlett-Packard Enterprise Development Company, L.P.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
*/
package com.autonomy.abc.selenium.find.filters;
import com.google.common.base.Function;
import com.hp.autonomy.frontend.selenium.element.ModalView;
import com.hp.autonomy.frontend.selenium.util.DriverUtil;
import com.hp.autonomy.frontend.selenium.util.ElementUtil;
import com.hp.autonomy.frontend.selenium.util.Locator;
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
public class ParametricFilterModal extends ModalView implements Iterable<ParametricModalCheckbox> {
//number of segments visible in sunburst - calculable from ParametricFilterModal
private static final int VISIBLE_SEGMENTS = 20;
private static final Logger LOGGER = LoggerFactory.getLogger(ParametricFilterModal.class);
private final WebDriver driver;
private ParametricFilterModal(final WebElement element, final WebDriver webDriver) {
super(element, webDriver);
driver = webDriver;
}
public static ParametricFilterModal getParametricModal(final WebDriver driver) {
final WebElement $el = new WebDriverWait(driver, 40)
.withMessage("Parametric filter modal did not open within 30 seconds ")
.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".fixed-height-modal")));
return new ParametricFilterModal($el, driver);
}
private static void waitUntilModalGone(final WebDriver driver) {
new WebDriverWait(driver, 30).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".fixed-height-modal")));
}
private static boolean isBigEnough(final int thisCount, final int totalResults) {
return (double) thisCount / totalResults >= 0.05;
}
public boolean isCurrentTabLoading() {
return findElements(By.cssSelector(".tab-pane.active .loading-spinner.hide")).isEmpty();
}
public void waitForLoad() {
new WebDriverWait(getDriver(), 15)
.withMessage("loading indicator to disappear")
.until((Function<? super WebDriver, Boolean>) webDriver -> !isCurrentTabLoading());
}
public void cancel() {
final Locator locator = new Locator()
.withTagName("button")
.containingText("Cancel");
findElement(locator).click();
waitUntilModalGone(driver);
}
public void apply() {
final Locator locator = new Locator()
.withTagName("button")
.containingText("Apply");
findElement(locator).click();
waitUntilModalGone(driver);
}
public List<WebElement> tabs() {
return findElements(By.cssSelector(".fields-list a"));
}
public String activeTabName() {
return findElement(By.cssSelector(".fields-list li.active span")).getText();
}
public List<String> tabNames() {
return findElements(By.cssSelector(".fields-list a span")).stream()
.map(WebElement::getText)
.collect(Collectors.toList());
}
//input 0-indexed like panel
public void goToTab(final int tabNumber) {
tabs().get(tabNumber).click();
}
public WebElement activePane() {
return findElement(By.cssSelector(".tab-pane.active"));
}
public List<WebElement> activePaneFilterList() {
scrollDownInsideModal();
return activePane().findElements(By.cssSelector(".checkbox.parametric-value-label"));
}
private void scrollDownInsideModal() {
final WebElement pane = activePane();
pane.click();
pane.click();
final int limit = 20;
int i = 0;
int numberOfValues = 0;
int previousNumber = -1;
int twicePreviousNumber = -1;
while (i < limit && filtersWithNoResults(pane) < 1 && twicePreviousNumber < numberOfValues) {
DriverUtil.scrollToBottom(driver);
twicePreviousNumber = previousNumber;
previousNumber = numberOfValues;
numberOfValues = pane.findElements(By.cssSelector(".checkbox.parametric-value-label")).size();
i++;
}
if (i >= limit) {
LOGGER.info("Loop reached limit of " + limit + " , " +
"but if there is v large number of categories the limit may need to be higher");
}
}
private int filtersWithNoResults(final SearchContext pane) {
final By locator = By.xpath(
".//*[contains(@class, 'checkbox') and " +
"contains(@class, 'parametric-value-label') and contains(.,'(0)')]"
);
return pane.findElements(locator).size();
}
public List<WebElement> allFilters() {
return findElements(By.cssSelector(".checkbox.parametric-value-label"));
}
public String checkCheckBoxInActivePane(final int i) {
final ParametricModalCheckbox box = new ParametricModalCheckbox(activePaneFilterList().get(i));
box.check();
return box.getName();
}
public List<String> checkedFiltersAllPanes() {
final List<String> allCheckedFilters = new ArrayList<>();
for (final WebElement tab : tabs()) {
tab.click();
allCheckedFilters.addAll(ElementUtil.getTexts(activePane().findElements(
By.cssSelector(".icheckbox-hp.checked + span")))
);
}
return allCheckedFilters;
}
@Override
public Iterator<ParametricModalCheckbox> iterator() {
return values().iterator();
}
public List<ParametricModalCheckbox> values() {
return activePaneFilterList().stream().map(ParametricModalCheckbox::new).collect(Collectors.toList());
}
private int totalResultsInPane(final Iterable<ParametricModalCheckbox> checkboxes) {
int totalResults = 0;
for (final ParametricModalCheckbox checkbox : checkboxes) {
if (checkbox.getResultsCount() != 0) {
totalResults += checkbox.getResultsCount();
} else {
break;
}
}
return totalResults;
}
public int filtersWithResultsForCurrentSearch() {
final Iterable<ParametricModalCheckbox> checkboxes = values();
int count = 0;
for (final ParametricModalCheckbox checkbox : checkboxes) {
if (checkbox.getResultsCount() != 0) {
count++;
} else {
break;
}
}
cancel();
return count;
}
public List<String> expectedParametricValues() {
final Iterable<ParametricModalCheckbox> checkboxes = values();
final List<String> expected = new ArrayList<>();
final int totalResults = totalResultsInPane(checkboxes);
for (final ParametricModalCheckbox checkbox : checkboxes) {
final int thisCount = checkbox.getResultsCount();
if ((expected.size() < VISIBLE_SEGMENTS || isBigEnough(thisCount, totalResults)) && thisCount != 0) {
expected.add(checkbox.getName());
} else {
break;
}
}
return expected;
}
}