Configuring synchronization behavior
Web automation can be challenging due to dynamic page loading, asynchronous content, and varying page response times. Kolibrium provides a flexible synchronization mechanism that goes beyond simple visibility checks, allowing developers to define precise conditions for element readiness.
Single elements: Defining readiness
By default, Kolibrium checks if an element is displayed using the WebElement
's isDisplayed
property.
val button by driver.id("submit-button") // Default behavior: checks if element is displayed
When working with web elements, simply checking if an element is displayed might not be sufficient. Kolibrium allows you to define complex readiness conditions using Kotlin's powerful lambda syntax.
Common practice is to wait until the element is displayed and enabled so it can be clicked.
In order to facilitate this waiting strategy, we can specify what WebElement
properties should be evaluated to be true
before performing an action on it.
This is done by providing a predicate that determines when the found element is considered ready for use.
val button by driver.id("button") { isDisplayed && isEnabled } // Wait until button is both visible and enabled
Or, by using Kolibrium's extension property on WebElement
, it can be simplified to
val button by driver.id("button") { isClickable }
where isClickable
is defined as
public val WebElement.isClickable: Boolean
get() = isDisplayed && isEnabled
If you are using IntelliJ IDEA or Aqua, and have enabled Inlay Hints (Settings -> Editor -> Inlay Hints -> Lambdas -> Kotlin -> Implicit receivers and parameters), you will see a this: WebElement
hint after the opening bracket.
This indicates that we have access to the WebElement
, meaning we can use other properties as well, such as isSelected
to determine when the element is ready for use.
In fact, we can write any code in between the bracket as long as it's evaluated to true
.
Speaking of true
: if we don't want to perform any checks on a WebElement
we can set the default waiting strategy to { true }
, which means the element is considered ready regardless of its state.
Advanced readiness conditions
The following locator definitions require all three conditions to be true
before being considered "ready".
val searchInput by driver.id("search-input") {
isDisplayed &&
getAttribute("placeholder")?.isNotEmpty() == true &&
isEnabled
}
val dynamicElement by driver.id("dynamic-content") {
isDisplayed &&
getAttribute("class")?.contains("loading") == false &&
text.contains("Ready")
}
Multiple elements: Collective readiness
When working with collections of elements, Kolibrium provides flexible synchronization strategies.
Wait until all elements are visible
val links by driver.classNames("navigation-link") // Default behavior: checks if all elements are displayed
Specific size validation
val productCards by driver.classNames(
lovator = "product",
cacheLookup = false,
) {
size == 9 // Wait until exactly 9 elements are present
}
Notice that element caching is disabled in this case. This is because, with caching enabled:
- Kolibrium would find the first element.
- Cache it for consecutive accesses, which also means it would stop searching for new elements appearing on the UI.
Advanced collection conditions
val formInputs by driver.cssSelectors("form input") {
all { it.isEnabled && it.getAttribute("value")?.isNotEmpty() == true } // Ensure all inputs are enabled and have values
}
Synchronization strategies for collections
all { }
: Every element must satisfy the condition.any { }
: At least one element must satisfy the condition.count { }
: Validates number of elements meeting a condition.