0

I would like to wait until a specific view disappears. In general, I can do it with the following code:

val wait = WebDriverWait(driver, Duration.ofSeconds(3)) // where driver is e.g. WebDriver
val condition = ExpectedConditions.invisibilityOfElementLocated(
    By.id("my.app:id/someId") // or another locator, e.g. XPath
)
wait.until(condition)

However, that way is not very precise.

Imagine a scenario with two different views matching the same predicate (locator). In the example below I used the "by ID" locator but it could be anything else, too.

In the image below, there are 3 views:

  • view "A" that matches my predicate ("by ID")
  • view "B" that contains view "C"
  • view "C" that matches my predicate ("by ID")

Two views matching the same locator

When I want to just find view "C", e.g. in order to click it, I can do this:

driver.findElement(By.id("anotherId")).findElement("someId").click()

so I can narrow down the search for view "C" by searching for view "B" first, when I know it contains view "C".

That is possible because WebElement returned by findElement method implements SearchContext interface, just like WebDriver does. Therefore, I can choose whether I want to search on the whole screen or inside a specific WebElement.

How can I narrow down the search in case of waiting for the view to disappear?

Ideally, I would expect something like:

ExpectedConditions.invisibilityOfElementLocated(
    searchContext, // either a driver or WebElement
    By.id(...) // the locator
)

but I haven't found anything like that.

Andrzej Zabost
  • 1,387
  • 11
  • 26

2 Answers2

0

I've looked throw the org.openqa.selenium.support.ui.ExpectedConditions methods..

There are some similar methods:

  • visibilityOfNestedElementsLocatedBy(final By parent, final By childLocator)

  • visibilityOfNestedElementsLocatedBy(final WebElement element, final By childLocator)

But no the same methods for invisibility.

So, I suggest implementing the custom one:

import org.openqa.selenium.support.ui.ExpectedCondition
import org.openqa.selenium.support.ui.ExpectedConditions

public static ExpectedCondition<Boolean> invisibilityOfNestedElementLocated(WebElement parent, By nested) {
    return new ExpectedCondition<Boolean>() {
        private boolean wasFound = false;

        @Override
        public Boolean apply(WebDriver driver) {
            wasFound = ExpectedConditions.invisibilityOfAllElements(parent.findElements(nested)).apply(driver);
            return wasFound;
        }

        @Override
        public String toString() {
            return String.format("element \"%s\" from parent \"%s\", found: \"%b\"", nested.toString(), parent.toString(), wasFound);
        }
    };
}

And for your example:

WebElement searchContext = driver.findElement(By.id("anotherId");
new WebDriverWait(driver, Duration.ofSeconds(10)).until(
    invisibilityOfNestedElementLocated(searchContext, By.id('someId'))
)
Max Daroshchanka
  • 2,698
  • 2
  • 10
  • 14
0

public static ExpectedCondition<java.lang.Boolean> stalenessOf​(WebElement element)

Wait until an element is no longer attached to the DOM.