geb.navigator.DefaultNavigator.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of geb-core Show documentation
Show all versions of geb-core Show documentation
Geb (pronounced "jeb") is a browser automation solution. It brings together the power of WebDriver, the elegance of jQuery content selection, the robustness of Page Object modelling and the expressiveness of the Groovy language.
/*
* Copyright 2010 the original author or authors.
*
* 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.
*/
package geb.navigator
import geb.Browser
import geb.Module
import geb.Page
import geb.content.ModuleBaseCalculator
import geb.error.SingleElementNavigatorOnlyMethodException
import geb.error.UnableToSetElementException
import geb.error.UnexpectedPageException
import geb.js.JQueryAdapter
import geb.navigator.event.BrowserConfigurationDelegatingNavigatorEventListener
import geb.navigator.event.NavigatorEventListener
import geb.navigator.factory.NavigatorFactory
import geb.waiting.PotentiallyWaitingExecutor
import geb.waiting.Wait
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FromString
import groovy.transform.stc.SimpleType
import org.openqa.selenium.By
import org.openqa.selenium.NoSuchElementException
import org.openqa.selenium.StaleElementReferenceException
import org.openqa.selenium.WebElement
import java.util.function.Supplier
import static java.util.Collections.EMPTY_LIST
import static geb.navigator.WebElementPredicates.matches
class DefaultNavigator implements Navigator {
protected final static BOOLEAN_ATTRIBUTES = ['async', 'autofocus', 'autoplay', 'checked', 'compact', 'complete',
'controls', 'declare', 'defaultchecked', 'defaultselected', 'defer', 'disabled', 'draggable', 'ended',
'formnovalidate', 'hidden', 'indeterminate', 'iscontenteditable', 'ismap', 'itemscope', 'loop',
'multiple', 'muted', 'nohref', 'noresize', 'noshade', 'novalidate', 'nowrap', 'open', 'paused',
'pubdate', 'readonly', 'required', 'reversed', 'scoped', 'seamless', 'seeking', 'selected',
'spellcheck', 'truespeed', 'willvalidate']
protected final static ELEMENTS_WITH_MUTABLE_VALUE = ['input', 'select', 'textarea']
final Browser browser
@Delegate(allNames = true)
final Locator locator
protected final Iterable contextElements
protected NavigatorEventListener eventListener
DefaultNavigator(Browser browser, Iterable extends WebElement> contextElements) {
this.browser = browser
this.locator = new DefaultLocator(new SearchContextBasedBasicLocator(contextElements, browser.navigatorFactory))
this.contextElements = contextElements
this.eventListener = new BrowserConfigurationDelegatingNavigatorEventListener(browser, this)
}
boolean asBoolean() {
!empty
}
@Override
Navigator filter(Map predicates, String selector) {
navigatorFor(dynamic(predicates)) {
contextElements.findAll(matchingSelectorAndPredicates(selector, predicates))
}
}
Navigator has(String selector) {
findAll { Navigator it ->
!it.find(selector).empty
}
}
Navigator has(Map predicates) {
navigatorForMatching(dynamic(predicates)) {
it.find(predicates)
}
}
Navigator has(Map predicates, String selector) {
navigatorForMatching(dynamic(predicates)) {
it.find(predicates, selector)
}
}
Navigator has(By bySelector) {
findAll { Navigator it ->
!it.find(bySelector).empty
}
}
Navigator has(Map predicates, By bySelector) {
navigatorForMatching(dynamic(predicates)) {
it.find(predicates, bySelector)
}
}
Navigator hasNot(String selector) {
findAll { Navigator it ->
it.find(selector).empty
}
}
Navigator hasNot(Map predicates) {
navigatorForMatching(dynamic(predicates)) {
it.find(predicates).empty
}
}
Navigator hasNot(Map predicates, String selector) {
navigatorForMatching(dynamic(predicates)) {
it.find(predicates, selector).empty
}
}
Navigator hasNot(By bySelector) {
findAll { Navigator it ->
it.find(bySelector).empty
}
}
Navigator hasNot(Map predicates, By bySelector) {
navigatorForMatching(dynamic(predicates)) {
it.find(predicates, bySelector).empty
}
}
Navigator eq(int index) {
this[index]
}
Navigator add(String selector) {
add(By.cssSelector(selector))
}
Navigator add(By bySelector) {
add browser.driver.findElements(bySelector)
}
Navigator add(WebElement[] elements) {
add Arrays.asList(elements)
}
Navigator add(Collection elements) {
List result = []
result.addAll allElements()
result.addAll elements
browser.navigatorFactory.createFromWebElements(result)
}
Navigator plus(Navigator navigator) {
add navigator.allElements()
}
String attr(String name) {
getAttribute(name)
}
WebElement firstElement() {
getElement(0)
}
WebElement lastElement() {
getElement(-1)
}
Iterator iterator() {
new NavigatorIterator()
}
Navigator findAll(Closure predicate) {
browser.navigatorFactory.createFromNavigators(super.findAll(predicate))
}
JQueryAdapter getJquery() {
new JQueryAdapter(this)
}
public T module(Class moduleClass) {
if (!Module.isAssignableFrom(moduleClass)) {
throw new IllegalArgumentException("$moduleClass is not a subclass of ${Module}")
}
module(moduleClass.newInstance())
}
public T module(T module) {
def baseNavigatorFactory = browser.navigatorFactory.relativeTo(this)
NavigatorFactory moduleBaseNavigatorFactory = ModuleBaseCalculator.calculate(browser, module,
baseNavigatorFactory, browser.driver.switchTo())
module.init(browser, moduleBaseNavigatorFactory)
module
}
public List moduleList(Class moduleClass) {
iterator()*.module(moduleClass)
}
@SuppressWarnings(["UnnecessaryCollectCall"])
public List moduleList(Closure moduleFactory) {
iterator().collect { it.module(moduleFactory.call()) }
}
@Override
String getStringRepresentation() {
getClass().name
}
@Override
void setEventListener(NavigatorEventListener listener) {
this.eventListener = listener
}
@Override
Navigator filter(String selector) {
navigatorFor contextElements.findAll { element ->
CssSelector.matches(element, selector)
}
}
@Override
Navigator filter(Map predicates) {
def dynamic = dynamic(predicates)
if (!dynamic || predicates.size() != 1) {
navigatorFor(dynamic) {
contextElements.findAll { matches(it, predicates) }
}
} else {
this
}
}
@Override
Navigator not(String selector) {
navigatorFor contextElements.findAll { element ->
!CssSelector.matches(element, selector)
}
}
@Override
Navigator not(Map predicates, String selector) {
navigatorFor(dynamic(predicates)) {
contextElements.findAll { element ->
!(CssSelector.matches(element, selector) && matches(element, predicates))
}
}
}
@Override
Navigator not(Map predicates) {
navigatorFor(dynamic(predicates)) {
contextElements.findAll { element ->
!matches(element, predicates)
}
}
}
@Override
Navigator getAt(int index) {
navigatorFor(Collections.singleton(getElement(index)))
}
@Override
Navigator getAt(Range range) {
navigatorFor getElements(range)
}
@Override
Navigator getAt(Collection indexes) {
navigatorFor getElements(indexes)
}
@Override
WebElement singleElement() {
ensureContainsAtMostSingleElement("singleElement")
}
@Override
Collection allElements() {
contextElements.toList()
}
@Override
Iterator elementIterator() {
contextElements.iterator()
}
WebElement getElement(int index) {
def elements = contextElements.toList()
if (elements) {
contextElements[index]
}
}
List getElements(Range range) {
def elements = contextElements.toList()
if (elements) {
elements[range]
}
}
List getElements(Collection indexes) {
contextElements.toList()[indexes]
}
@Override
Navigator remove(int index) {
int size = size()
if (!(index in -size.. attributes) {
navigatorFor(dynamic(attributes)) {
collectFollowingSiblings {
it.find { matches(it, attributes) }
}
}
}
@Override
Navigator next(Map predicates = [:], String selector) {
navigatorFor(dynamic(predicates)) {
collectFollowingSiblings {
it.find(matchingSelectorAndPredicates(selector, predicates))
}
}
}
@Override
Navigator nextAll() {
navigatorFor collectFollowingSiblings()
}
@Override
Navigator nextAll(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectFollowingSiblings {
it.findAll { matches(it, attributes) }
}
}
}
@Override
Navigator nextAll(Map predicates = [:], String selector) {
navigatorFor(dynamic(predicates)) {
collectFollowingSiblings {
it.findAll(matchingSelectorAndPredicates(selector, predicates))
}
}
}
@Override
Navigator nextUntil(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectFollowingSiblings {
collectUntil(it, attributes)
}
}
}
@Override
Navigator nextUntil(Map attributes = [:], String selector) {
navigatorFor(dynamic(attributes)) {
collectFollowingSiblings {
collectUntil(it, attributes, selector)
}
}
}
@Override
Navigator previous() {
navigatorFor collectPreviousSiblings {
it ? it.last() : EMPTY_LIST
}
}
@Override
Navigator previous(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectPreviousSiblings {
it.reverse().find { matches(it, attributes) }
}
}
}
@Override
Navigator previous(Map predicates = [:], String selector) {
navigatorFor(dynamic(predicates)) {
collectPreviousSiblings {
it.reverse().find(matchingSelectorAndPredicates(selector, predicates))
}
}
}
@Override
Navigator prevAll() {
navigatorFor collectPreviousSiblings()
}
@Override
Navigator prevAll(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectPreviousSiblings {
it.reverse().findAll { matches(it, attributes) }
}
}
}
@Override
Navigator prevAll(Map predicates = [:], String selector) {
navigatorFor(dynamic(predicates)) {
collectPreviousSiblings {
it.reverse().findAll(matchingSelectorAndPredicates(selector, predicates))
}
}
}
@Override
Navigator prevUntil(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectPreviousSiblings {
collectUntil(it.reverse(), attributes)
}
}
}
@Override
Navigator prevUntil(Map attributes = [:], String selector) {
navigatorFor(dynamic(attributes)) {
collectPreviousSiblings {
collectUntil(it.reverse(), attributes, selector)
}
}
}
@Override
Navigator parent() {
navigatorFor collectParents()
}
@Override
Navigator parent(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectParents {
it.findAll { matches(it, attributes) }
}
}
}
@Override
Navigator parent(Map predicates = [:], String selector) {
navigatorFor(dynamic(predicates)) {
collectParents {
it.findAll(matchingSelectorAndPredicates(selector, predicates))
}
}
}
@Override
Navigator parents() {
navigatorFor collectAncestors {
it.reverse()
}
}
@Override
Navigator parents(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectAncestors {
it.reverse().findAll { matches(it, attributes) }
}
}
}
@Override
Navigator parents(Map predicates = [:], String selector) {
navigatorFor(dynamic(predicates)) {
collectAncestors {
it.reverse().findAll(matchingSelectorAndPredicates(selector, predicates))
}
}
}
@Override
Navigator parentsUntil(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectAncestors {
collectUntil(it.reverse(), attributes)
}
}
}
@Override
Navigator parentsUntil(Map attributes = [:], String selector) {
navigatorFor(dynamic(attributes)) {
collectAncestors {
collectUntil(it.reverse(), attributes, selector)
}
}
}
@Override
Navigator closest(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectAncestors {
it.reverse().find { matches(it, attributes) }
}
}
}
@Override
Navigator closest(Map predicates = [:], String selector) {
navigatorFor(dynamic(predicates)) {
collectAncestors {
it.reverse().find(matchingSelectorAndPredicates(selector, predicates))
}
}
}
@Override
Navigator children() {
navigatorFor collectChildren()
}
@Override
Navigator children(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectChildren {
it.findAll { matches(it, attributes) }
}
}
}
@Override
Navigator children(Map predicates = [:], String selector) {
navigatorFor(dynamic(predicates)) {
collectChildren {
it.findAll(matchingSelectorAndPredicates(selector, predicates))
}
}
}
@Override
Navigator siblings() {
navigatorFor collectSiblings()
}
@Override
Navigator siblings(Map attributes) {
navigatorFor(dynamic(attributes)) {
collectSiblings {
it.findAll { matches(it, attributes) }
}
}
}
@Override
Navigator siblings(Map predicates = [:], String selector) {
navigatorFor(dynamic(predicates)) {
collectSiblings {
it.findAll(matchingSelectorAndPredicates(selector, predicates))
}
}
}
@Override
boolean hasClass(String valueToContain) {
valueToContain in elementClasses(ensureContainsAtMostSingleElement("hasClass", String))
}
@Override
boolean is(String tag) {
tag.equalsIgnoreCase(ensureContainsAtMostSingleElement("is", String)?.tagName)
}
@Override
boolean isDisplayed() {
ensureContainsAtMostSingleElement("isDisplayed")?.displayed
}
@Override
String tag() {
ensureContainsAtMostSingleElement("tag")?.tagName
}
@Override
String text() {
ensureContainsAtMostSingleElement("text")?.text
}
@Override
String getAttribute(String name) {
def element = ensureContainsAtMostSingleElement("getAttribute", String)
if (element) {
def attribute = element.getAttribute(name)
if (attribute == 'false' && name in BOOLEAN_ATTRIBUTES) {
attribute = null
}
attribute == null ? "" : attribute
}
}
@Override
List classes() {
elementClasses(ensureContainsAtMostSingleElement("classes"))
}
@Override
def value() {
def element = ensureContainsAtMostSingleElement("value")
if (element) {
getInputValue(element)
}
}
@Override
Navigator value(value) {
eventListener.beforeValueSet(browser, this, value)
setInputValues(contextElements, value)
eventListener.afterValueSet(browser, this, value)
this
}
@Override
Navigator leftShift(value) {
eventListener.beforeSendKeys(browser, this, value)
contextElements.each {
it.sendKeys value
}
eventListener.afterSendKeys(browser, this, value)
this
}
@Override
Navigator click() {
def element = ensureContainsAtMostSingleElement("click")
if (element) {
eventListener.beforeClick(browser, this)
element.click()
eventListener.afterClick(browser, this)
} else {
throw new UnsupportedOperationException("not supported on empty navigator objects")
}
this
}
@Override
Navigator click(Class extends Page> pageClass, Wait wait = null) {
click(browser.createPage(pageClass), wait)
}
@Override
Navigator click(Page pageInstance, Wait wait = null) {
click()
browser.page(pageInstance)
def at = false
def assertionError = null
def throwable = null
try {
if (pageInstance.shouldVerifyAtImplicitly) {
at = new PotentiallyWaitingExecutor(wait).execute { browser.verifyAt() }
} else {
at = true
}
} catch (AssertionError e) {
assertionError = e
} catch (Throwable e) {
throwable = e
throw e
} finally {
if (!at && !throwable) {
throw new UnexpectedPageException(pageInstance, (Throwable) assertionError)
}
}
this
}
@Override
Navigator click(List potentialPages, Wait wait = null) {
click()
new PotentiallyWaitingExecutor(wait).execute { browser.page(*potentialPages) }
this
}
@Override
int size() {
contextElements.size()
}
@Override
boolean isEmpty() {
size() == 0
}
@Override
Navigator head() {
first()
}
@Override
Navigator first() {
navigatorFor(Collections.singleton(firstElement()))
}
@Override
Navigator last() {
navigatorFor(Collections.singleton(lastElement()))
}
@Override
Navigator tail() {
def elements = contextElements.toList()
def tail = elements ? elements.tail() : []
navigatorFor tail
}
@Override
Navigator verifyNotEmpty() {
if (empty) {
throw new EmptyNavigatorException()
}
this
}
@Override
int getHeight() {
ensureContainsAtMostSingleElement("getHeight")?.size?.height ?: 0
}
@Override
int getWidth() {
ensureContainsAtMostSingleElement("getWidth")?.size?.width ?: 0
}
@Override
int getX() {
ensureContainsAtMostSingleElement("getX")?.location?.x ?: 0
}
@Override
int getY() {
ensureContainsAtMostSingleElement("getY")?.location?.y ?: 0
}
@Override
Navigator unique() {
navigatorFor(allElements().unique(false))
}
@Override
String toString() {
contextElements*.toString()
}
@Override
String css(String propertyName) {
ensureContainsAtMostSingleElement("css", String)?.getCssValue(propertyName)
}
@Override
boolean isFocused() {
ensureContainsAtMostSingleElement("isFocused") == browser.driver.switchTo().activeElement()
}
def methodMissing(String name, arguments) {
def elements = allElements()
if (!arguments) {
def navigator = navigatorFor elements.collectMany {
it.findElements By.name(name)
}
if (!navigator.empty || !elements) {
return navigator
}
}
throw new MissingMethodException(name, getClass(), arguments)
}
def propertyMissing(String name) {
switch (name) {
case ~/@.+/:
return getAttribute(name.substring(1))
default:
def inputs = collectElements {
it.findElements(By.name(name))
}
if (inputs) {
return getInputValues(inputs)
}
throw new MissingPropertyException(name, getClass())
}
}
def propertyMissing(String name, value) {
def inputs = collectElements {
it.findElements(By.name(name))
}
if (inputs) {
setInputValues(inputs, value)
} else {
throw new MissingPropertyException(name, getClass())
}
}
@Override
int hashCode() {
allElements().hashCode()
}
@Override
boolean equals(Object obj) {
if (obj instanceof Navigator) {
allElements() == obj.allElements()
}
}
protected WebElement ensureContainsAtMostSingleElement(String name, Class>... parameterTypes) {
def elements = allElements()
if (elements.size() > 1) {
throw new SingleElementNavigatorOnlyMethodException(Navigator.getMethod(name, parameterTypes), elements.size())
}
if (elements) {
elements.first()
}
}
protected Navigator navigatorFor(Collection contextElements) {
browser.navigatorFactory.createFromWebElements(contextElements)
}
protected Navigator navigatorFor(boolean dynamic, Supplier> contextElementsSupplier) {
def elements = dynamic ? toDynamicIterable(contextElementsSupplier) : contextElementsSupplier.get()
browser.navigatorFactory.createFromWebElements(elements)
}
protected Navigator navigatorForMatching(boolean dynamic, @ClosureParams(value = SimpleType, options = "geb.navigator.Navigator") Closure> partialNavigatorPredicate) {
navigatorFor(dynamic) {
contextElements.findAll { element ->
partialNavigatorPredicate.call(navigatorFor(Collections.singleton(element)))
}
}
}
protected Iterable toDynamicIterable(Supplier> contextElementsSupplier) {
{ -> contextElementsSupplier.get().iterator() } as Iterable
}
protected getInputValues(Collection inputs) {
def values = []
inputs.each { WebElement input ->
def value = getInputValue(input)
if (value != null) {
values << value
}
}
values.size() < 2 ? values[0] : values
}
protected getInputValue(WebElement input) {
def value = null
def type = input.getAttribute("type")
if (input.tagName == "select") {
def select = new SelectFactory().createSelectFor(input)
if (select.multiple) {
value = select.allSelectedOptions.collect { getValue(it) }
} else {
value = getValue(select.firstSelectedOption)
}
} else if (type in ["checkbox", "radio"]) {
if (input.isSelected()) {
value = getValue(input)
}
} else {
value = getValue(input)
}
value
}
protected void setInputValues(Iterable inputs, value) {
def inputsToTagNames = inputs.collectEntries { [it, it.tagName.toLowerCase()] }
def unsupportedElements = inputsToTagNames.values() - ELEMENTS_WITH_MUTABLE_VALUE
if (unsupportedElements) {
throw new UnableToSetElementException(*unsupportedElements)
}
inputsToTagNames.inject(false) { boolean valueSet, WebElement input, String tagName ->
setInputValue(input, tagName, value, valueSet) || valueSet
}
}
protected boolean setInputValue(WebElement input, String tagName, value, boolean suppressStaleElementException) {
boolean valueSet = false
try {
def type = input.getAttribute("type")
if (tagName == "select") {
setSelectValue(input, value)
valueSet = true
} else if (type == "checkbox") {
valueSet = setCheckboxValue(input, value)
} else if (type == "radio") {
if (getValue(input) == value.toString() || labelFor(input) == value.toString()) {
input.click()
valueSet = true
}
} else if (type == "file") {
input.sendKeys value as String
valueSet = true
} else if (type in ["color", "date", "datetime-local", "time", "range", "month", "week"]) {
browser.js.exec(input, value as String, 'arguments[0].setAttribute("value", arguments[1]);')
valueSet = true
} else {
input.clear()
input.sendKeys value as String
valueSet = true
}
} catch (StaleElementReferenceException e) {
if (!suppressStaleElementException) {
throw e
}
} finally {
valueSet
}
}
protected getValue(WebElement input) {
input?.getAttribute("value")
}
protected setSelectValue(WebElement element, value) {
def select = new SelectFactory().createSelectFor(element)
def multiple = select.multiple
if (multiple) {
select.deselectAll()
}
if (value == null || (value instanceof Collection && value.empty)) {
if (multiple) {
return
}
nonexistentSelectOptionSelected(value.toString(), select)
}
def valueStrings
if (multiple) {
valueStrings = (value instanceof Collection ? new LinkedList(value) : [value])*.toString()
} else {
valueStrings = [value.toString()]
}
for (valueString in valueStrings) {
try {
select.selectByValue(valueString)
} catch (NoSuchElementException e1) {
try {
select.selectByVisibleText(valueString)
} catch (NoSuchElementException e2) {
nonexistentSelectOptionSelected(valueString, select)
}
}
}
}
private void nonexistentSelectOptionSelected(String valueString, select) {
def availableValues = select.options*.getAttribute("value")
def availableTexts = select.options*.getText()
throw new IllegalArgumentException("Couldn't select option with text or value: $valueString, available texts: $availableTexts, available values: $availableValues")
}
protected boolean unselect(WebElement input) {
if (input.isSelected()) {
input.click()
true
}
}
protected boolean select(WebElement input) {
if (!input.isSelected()) {
input.click()
true
}
}
protected boolean setCheckboxValue(WebElement input, value) {
if (value == null || value == false || (value instanceof Collection && value.empty)) {
unselect(input)
} else if (value == true) {
select(input)
} else {
def values = value instanceof Collection ? value*.toString() : [value]
if (getValue(input) in values || labelFor(input) in values) {
select(input)
} else {
unselect(input)
}
}
}
protected String labelFor(WebElement input) {
def id = input.getAttribute("id")
def labels = browser.driver.findElements(By.xpath("//label[@for='$id']")) ?: input.findElements(By.xpath("ancestor::label"))
labels ? labels[0].text : null
}
protected List collectElements(@ClosureParams(value = SimpleType, options = "org.openqa.selenium.WebElement") Closure closure) {
List list = []
contextElements.each {
try {
def value = closure(it)
switch (value) {
case Collection:
list.addAll value
break
default:
if (value) {
list << value
}
}
} catch (NoSuchElementException e) {
}
}
list
}
protected Collection collectUntil(Collection elements, Closure matcher) {
int index = elements.findIndexOf matcher
index == -1 ? elements : elements[0.. collectUntil(Collection elements, Map attributes) {
collectUntil(elements) { matches(it, attributes) }
}
protected Collection collectUntil(Collection elements, Map attributes, String selector) {
collectUntil(elements) { CssSelector.matches(it, selector) && matches(it, attributes) }
}
protected Collection collectRelativeElements(String xpath, @ClosureParams(value = FromString, options = "java.util.List") Closure filter) {
collectElements {
def elements = it.findElements(By.xpath(xpath))
filter ? filter(elements) : elements
}
}
protected Collection collectFollowingSiblings(@ClosureParams(value = FromString, options = "java.util.List") Closure filter) {
collectRelativeElements("following-sibling::*", filter)
}
protected Collection collectPreviousSiblings(@ClosureParams(value = FromString, options = "java.util.List") Closure filter) {
collectRelativeElements("preceding-sibling::*", filter)
}
protected Collection collectParents(@ClosureParams(value = FromString, options = "java.util.List") Closure filter) {
collectRelativeElements("parent::*", filter)
}
protected Collection collectAncestors(@ClosureParams(value = FromString, options = "java.util.List") Closure filter) {
collectRelativeElements("ancestor::*", filter)
}
protected Collection collectChildren(@ClosureParams(value = FromString, options = "java.util.List") Closure filter) {
collectRelativeElements("child::*", filter)
}
protected Collection collectSiblings(@ClosureParams(value = FromString, options = "java.util.List") Closure filter) {
collectElements {
def elements = it.findElements(By.xpath("preceding-sibling::*")) + it.findElements(By.xpath("following-sibling::*"))
filter ? filter(elements) : elements
}
}
protected List elementClasses(WebElement element) {
element?.getAttribute("class")?.tokenize()?.unique()?.sort() ?: EMPTY_LIST
}
protected Closure matchingSelectorAndPredicates(String selector, Map predicates) {
{ WebElement element -> CssSelector.matches(element, selector) && matches(element, predicates) }
}
/**
* Iterator for looping over the context elements of a Navigator instance.
*/
private class NavigatorIterator implements Iterator {
private int index
boolean hasNext() {
index < DefaultNavigator.this.size()
}
Navigator next() {
DefaultNavigator.this[index++]
}
void remove() {
throw new UnsupportedOperationException()
}
}
protected boolean dynamic(Map attributes) {
attributes[DYNAMIC_ATTRIBUTE_NAME]
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy