Skip to content
43 changes: 43 additions & 0 deletions src/main/java/aquality/selenium/elements/DesiredState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package aquality.selenium.elements;

import org.openqa.selenium.WebElement;

import java.util.function.Predicate;

class DesiredState {

private final Predicate<WebElement> desiredStatePredicate;
private final String message;
private final boolean isCatchableInTimeoutException;
private final boolean isThrowableNoSuchException;

DesiredState(Predicate<WebElement> desiredStatePredicate, String message, boolean isCatchableInTimeoutException, boolean isThrowableNoSuchException){
this.desiredStatePredicate = desiredStatePredicate;
this.message = message;
this.isCatchableInTimeoutException = isCatchableInTimeoutException;
this.isThrowableNoSuchException = isThrowableNoSuchException;
}

DesiredState(Predicate<WebElement> desiredStatePredicate, String message){
this.desiredStatePredicate = desiredStatePredicate;
this.message = message;
this.isCatchableInTimeoutException = true;
this.isThrowableNoSuchException = true;
}

public Predicate<WebElement> getDesiredStatePredicate() {
return desiredStatePredicate;
}

public String getMessage() {
return message;
}

public boolean isCatchableInTimeoutException() {
return isCatchableInTimeoutException;
}

public boolean isThrowableNoSuchException() {
return isThrowableNoSuchException;
}
}
83 changes: 15 additions & 68 deletions src/main/java/aquality/selenium/elements/Element.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
import aquality.selenium.localization.LocalizationManager;
import aquality.selenium.logger.Logger;
import aquality.selenium.waitings.ConditionalWait;
import org.openqa.selenium.*;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.RemoteWebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;

/**
* Abstract class, describing wrapper of WebElement.
Expand All @@ -24,9 +25,6 @@ public abstract class Element implements IElement {
private static final String LOG_DELIMITER = "::";
private static final String LOG_CLICKING = "loc.clicking";

private final Configuration configuration = Configuration.getInstance();
private final long timeoutCondition = configuration.getTimeoutConfiguration().getCondition();

/**
* Name of element
*/
Expand Down Expand Up @@ -63,7 +61,7 @@ protected Element(final By loc, final String nameOf, final ElementState stateOf)

@Override
public RemoteWebElement getElement() {
return getElement(timeoutCondition);
return getElement(getDefaultTimeout());
}

@Override
Expand All @@ -79,17 +77,6 @@ public RemoteWebElement getElement(Long timeout) {
}
}

@Override
public boolean isEnabled(long timeout) {
return ConditionalWait.waitForTrue(y -> getElement().isEnabled()
&& !hasState(PopularClassNames.DISABLED), timeout);
}

@Override
public boolean isEnabled() {
return isEnabled(timeoutCondition);
}

@Override
public By getLocator() {
return locator;
Expand Down Expand Up @@ -122,28 +109,16 @@ public void sendKeys(Keys key) {

@Override
public void waitAndClick() {
waitForElementClickable();
state().waitForClickable();
info(getLocManager().getValue(LOG_CLICKING));
click();
}

@Override
public void waitForElementClickable() {
waitForElementClickable(timeoutCondition);
}

@Override
public void waitForElementClickable(Long timeout) {
ConditionalWait.waitFor(ExpectedConditions.elementToBeClickable(getLocator()), timeout);
}

@Override
public void click() {
getJsActions().highlightElement();
ConditionalWait.waitFor(y -> {
WebElement el = getElement();
info(getLocManager().getValue(LOG_CLICKING));
el.click();
getElement().click();
return true;
});
}
Expand All @@ -161,48 +136,21 @@ public String getText() {

@Override
public String getText(HighlightState highlightState) {
Logger.getInstance().info(getLocManager().getValue("loc.get.text"));
info(getLocManager().getValue("loc.get.text"));
if(highlightState.equals(HighlightState.HIGHLIGHT)){
getJsActions().highlightElement();
}
if(ElementFinder.getInstance().findElements(locator, timeoutCondition, state).isEmpty()){
throw new IllegalStateException(String.format(getLocManager().getValue("loc.element.wasnotfoundinstate"), getName(), state, timeoutCondition));
}
return ConditionalWait.waitFor(y -> getElement().getText());
}

@Override
public boolean waitForDisplayed(long timeout) {
getLogger().info(getLocManager().getValue("loc.waitinstate"), ElementState.DISPLAYED, getLocator());
return IElement.super.waitForDisplayed(timeout);
}

@Override
public boolean waitForExist(long timeout) {
getLogger().info(getLocManager().getValue("loc.waitexists"));
return IElement.super.waitForExist(timeout);
}

@Override
public boolean waitForNotDisplayed(long timeout) {
getLogger().info(getLocManager().getValue("loc.waitinvisible"));
return IElement.super.waitForNotDisplayed(timeout);
}

@Override
public boolean waitForNotExist(long timeout) {
getLogger().info(getLocManager().getValue("loc.waitnotexists"), timeout);
return IElement.super.waitForNotExist(timeout);
}

@Override
public IElementStateProvider state() {
return elementStateProvider;
}

@Override
public String getAttribute(final String attr, HighlightState highlightState) {
getLogger().info(getLocManager().getValue("loc.el.getattr"), attr);
info(String.format(getLocManager().getValue("loc.el.getattr"), attr));
if (highlightState.equals(HighlightState.HIGHLIGHT)) {
getJsActions().highlightElement();
}
Expand All @@ -216,7 +164,7 @@ public String getAttribute(final String attr) {

@Override
public String getCssValue(final String propertyName, HighlightState highlightState) {
getLogger().info(getLocManager().getValue("loc.el.cssvalue"), propertyName);
info(String.format(getLocManager().getValue("loc.el.cssvalue"), propertyName));
if (highlightState.equals(HighlightState.HIGHLIGHT)) {
getJsActions().highlightElement();
}
Expand All @@ -231,13 +179,13 @@ public String getCssValue(final String propertyName) {
@Override
public void setInnerHtml(final String value) {
click();
getLogger().info(getLocManager().getValue("loc.send.text"), value);
info(String.format(getLocManager().getValue("loc.send.text"), value));
getBrowser().executeScript(JavaScript.SET_INNER_HTML.getScript(), getElement(), value);
}

@Override
public void clickRight() {
getLogger().info(getLocManager().getValue("loc.clicking.right"));
info(String.format(getLocManager().getValue("loc.clicking.right")));
ConditionalWait.waitFor(y -> {
Actions actions = new Actions(getBrowser().getDriver());
actions.moveToElement(getElement());
Expand Down Expand Up @@ -282,11 +230,6 @@ public MouseActions getMouseActions() {
return new MouseActions(this, getElementType(), getName());
}

@Override
public boolean hasState(String className) {
return getAttribute(Attributes.CLASS.toString()).toLowerCase().contains(className.toLowerCase());
}

@Override
public <T extends IElement> T findChildElement(By childLoc, ElementType type, ElementState state) {
return new ElementFactory().findChildElement(this, childLoc, type, state);
Expand All @@ -309,4 +252,8 @@ protected Logger getLogger(){
protected LocalizationManager getLocManager(){
return LocalizationManager.getInstance();
}

long getDefaultTimeout(){
return Configuration.getInstance().getTimeoutConfiguration().getCondition();
}
}
96 changes: 74 additions & 22 deletions src/main/java/aquality/selenium/elements/ElementFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
import aquality.selenium.configuration.Configuration;
import aquality.selenium.configuration.ITimeoutConfiguration;
import aquality.selenium.elements.interfaces.IElementFinder;
import aquality.selenium.localization.LocalizationManager;
import aquality.selenium.logger.Logger;
import aquality.selenium.waitings.ConditionalWait;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebElement;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Collectors;

class ElementFinder implements IElementFinder {
private static final ThreadLocal<ElementFinder> instanceHolder = new ThreadLocal<>();
Expand Down Expand Up @@ -45,37 +51,75 @@ public WebElement findElement(By locator, long timeout, ElementState state) {

@Override
public List<WebElement> findElements(By locator, long timeout, ElementState state) {
switch (state) {
case DISPLAYED:
return findElements(locator, timeout, new DesiredState(WebElement::isDisplayed, String.format(getLocManager().getValue("loc.no.elements.found.in.state"), locator, "DISPLAYED", timeout)));
case EXISTS_IN_ANY_STATE:
return findElements(locator, timeout, new DesiredState(Objects::nonNull, String.format(getLocManager().getValue("loc.no.elements.found.in.state"), locator, "EXIST", timeout)));
default:
String errorMessage = String.format("'%s' state is not recognized", state.toString());
throw new IllegalArgumentException(errorMessage);
}
}

List<WebElement> findElements(By locator, long timeout, DesiredState desiredState)
{
List<WebElement> foundElements = new ArrayList<>();
List<WebElement> resultElements = new ArrayList<>();
long zeroTimeout = 0L;
getBrowser().setImplicitWaitTimeOut(zeroTimeout);
ConditionalWait.waitForTrue(y -> {
List<WebElement> foundElements = getBrowser().getDriver().findElements(locator);
List<WebElement> filteredElements = filterByState(foundElements, state);
resultElements.addAll(filteredElements);
return !filteredElements.isEmpty();
}, timeout);
try{
ConditionalWait.waitForTrue(driver ->
{
List<WebElement> allFoundElements = getBrowser().getDriver().findElements(locator);
foundElements.addAll(allFoundElements);
List<WebElement> filteredElements = filterByState(allFoundElements, desiredState.getDesiredStatePredicate());
resultElements.addAll(filteredElements);
return !filteredElements.isEmpty();
}, timeout);
}catch (TimeoutException e){
applyResult(locator, desiredState, foundElements);
}
getBrowser().setImplicitWaitTimeOut(getTimeoutConfiguration().getImplicit());
return resultElements;
}

private List<WebElement> filterByState(List<WebElement> foundElements, ElementState state){
List<WebElement> filteredElements = new ArrayList<>();
if(!foundElements.isEmpty()){
for (WebElement foundElement : foundElements) {
switch (state) {
case DISPLAYED:
if (foundElement.isDisplayed()) {
filteredElements.add(foundElement);
}
break;
case EXISTS_IN_ANY_STATE:
filteredElements.add(foundElement);
break;
default:
String errorMessage = String.format("'%s' state is not recognized", state.toString());
throw new IllegalArgumentException(errorMessage);
/**
* depends on configuration of DesiredState object it can be required to throw or not NoSuchElementException
* @param locator locator that is using to find elements
* @param desiredState DesiredState object
* @param foundElements list of all found elements by locator.
*/
private void applyResult(By locator, DesiredState desiredState, List<WebElement> foundElements){
if (desiredState.isCatchableInTimeoutException()){
if(foundElements.isEmpty()){
String message = String.format(getLocManager().getValue("loc.no.elements.found.by.locator"), locator);
if(desiredState.isThrowableNoSuchException()){
throw new NoSuchElementException(message);
}
getLogger().debug(message);
}else {
getLogger().debug(String.format(getLocManager().getValue("loc.elements.were.found.but.not.in.state"), locator, desiredState.getMessage()));
}
}else {
throw new TimeoutException(desiredState.getMessage());
}
}

/**
* tries to find list of elements in the DOM during defined timeout
* @param locator locator to find elements
* @param timeout timeout
* @return list of elements ot empty list if no elements found
*/
public List<WebElement> findElements(By locator, long timeout) {
return findElements(locator, timeout, ElementState.EXISTS_IN_ANY_STATE);
}

private List<WebElement> filterByState(List<WebElement> foundElements, Predicate<WebElement> desiredElementState){
List<WebElement> filteredElements = new ArrayList<>();
if(!foundElements.isEmpty()){
filteredElements.addAll(foundElements.stream().filter(desiredElementState).collect(Collectors.toList()));
}
return filteredElements;
}
Expand All @@ -87,4 +131,12 @@ private Browser getBrowser() {
private ITimeoutConfiguration getTimeoutConfiguration() {
return Configuration.getInstance().getTimeoutConfiguration();
}

private Logger getLogger(){
return Logger.getInstance();
}

private LocalizationManager getLocManager(){
return LocalizationManager.getInstance();
}
}
Loading