com.redhat.darcy.webdriver.elements.WebDriverElement Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of darcy-webdriver Show documentation
Show all versions of darcy-webdriver Show documentation
An implementation of darcy and darcy-web that uses Selenium WebDriver as the automation library backend.
The newest version!
/*
Copyright 2014 Red Hat, Inc. and/or its affiliates.
This file is part of darcy-webdriver.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
package com.redhat.darcy.webdriver.elements;
import com.redhat.darcy.ui.ElementNotDisplayedException;
import com.redhat.darcy.ui.FindableNotPresentException;
import com.redhat.darcy.ui.api.ElementContext;
import com.redhat.darcy.ui.api.elements.Element;
import com.redhat.darcy.util.Caching;
import com.redhat.darcy.web.api.elements.HtmlElement;
import com.redhat.darcy.webdriver.internal.ElementLookup;
import org.openqa.selenium.ElementNotVisibleException;
import org.openqa.selenium.NotFoundException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.internal.WrapsElement;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
public class WebDriverElement implements Element, Caching, HtmlElement, WrapsElement {
/**
* Subclasses should not really be using this directly.
* @see #attempt(java.util.function.Consumer)
* @see #attemptAndGet(java.util.function.Function)
*/
protected final ElementLookup source;
private final ElementContext context;
private WebElement cached;
/**
* @param source Provides a means to lookup the backing {@link org.openqa.selenium.WebElement}
* for this WebDriverElement.
* @param context The context in which this element was found. Using this context will not nest
* underneath this element (by you may do so by using {@code By.nested(this, ...);}.
*/
public WebDriverElement(ElementLookup source, ElementContext context) {
this.source = source;
this.context = context;
}
@Override
public boolean isDisplayed() {
try {
return attemptAndGet(WebElement::isDisplayed);
} catch (FindableNotPresentException e) {
return false;
}
}
@Override
public boolean isPresent() {
try {
getWrappedElement();
return true;
} catch (NotFoundException e) {
return false;
}
}
@Override
public void click() {
attempt(WebElement::click);
}
@Override
public String getTagName() {
return attemptAndGet(WebElement::getTagName);
}
@Override
public String getCssValue(String property) {
return attemptAndGet(e -> e.getCssValue(property));
}
@Override
public List getClasses() {
String classList = getAttribute("class");
if (classList == null || classList.isEmpty()) {
return Collections.emptyList();
}
return Arrays.stream(classList.split(" "))
.collect(Collectors.toList());
}
@Override
public String getAttribute(String attribute) {
return attemptAndGet(e -> e.getAttribute(attribute));
}
/**
* Looks up the underlying source {@link org.openqa.selenium.WebElement}. If the element is no
* longer present, a {@link org.openqa.selenium.NoSuchElementException} may be thrown.
*/
@Override
public WebElement getWrappedElement() {
return source.lookup();
}
@Override
public void invalidateCache() {
cached = null;
}
@Override
public String toString() {
return "A WebDriverElement backed by, " + source;
}
/**
* Retrieve the ElementContext that this element was found in. Intended to allow element types
* to find other elements within the same context, most likely by nesting within themselves. For
* example, {@code return By.nested(this, By.htmlTag("option")).findAll(SelectOption.class,
* getContext());}.
*/
public ElementContext getContext() {
return context;
}
/**
* Expected way for sub element types to interact with their corresponding WebElement. This
* attempts the desired action, and will throw appropriate exceptions should the element not be
* able to be interacted with, for whatever reason. If the WebElement is stale when the action
* is attempted, the cached WebElement will be cleared and looked up again, which may lookup a
* fresh reference to the equivalent element.
*
* @param action A function that wraps the action to be performed. Accepts the source WebElement
* as its only parameter and returns nothing.
*/
protected void attempt(Consumer action) {
try {
action.accept(webElement());
} catch (StaleElementReferenceException e) {
invalidateCache();
try {
action.accept(webElement());
} catch (ElementNotVisibleException e1) {
throw new ElementNotDisplayedException(this, e1);
}
} catch (ElementNotVisibleException e) {
throw new ElementNotDisplayedException(this, e);
}
}
/**
* Expected way for sub element types to interact with their corresponding WebElement. This
* attempts the desired action, and will throw appropriate exceptions should the element not be
* able to be interacted with, for whatever reason. If the WebElement is stale when the action
* is attempted, the cached WebElement will be cleared and looked up again, which may lookup a
* fresh reference to the equivalent element.
*
* @param action A function that wraps the action to be performed. Accepts the source WebElement
* as its only parameter and returns the result of this action.
* @param Return type of the action.
* @return Whatever the action returns.
*/
protected T attemptAndGet(Function action) {
try {
return action.apply(webElement());
} catch (StaleElementReferenceException e) {
invalidateCache();
try {
return action.apply(webElement());
} catch (ElementNotVisibleException e1) {
throw new ElementNotDisplayedException(this, e1);
}
} catch (ElementNotVisibleException e) {
throw new ElementNotDisplayedException(this, e);
}
}
private WebElement webElement() {
if (cached == null) {
try {
cached = getWrappedElement();
} catch (NotFoundException e) {
throw new FindableNotPresentException(this, e);
}
}
return cached;
}
}