Nagendra Gupta
Nagendra Gupta

Reputation: 31

Selenium java, wait for element by xpath and matching text in case of xpath matching multiple elements

I'm trying to wait for an element with certain css and inner text. I have multiple elements satisfying the css condition (element could be visible/invisible) and selenium ExpectedConditions is not behaving the way I want.

If I try to find elements by css first and then filter out myself, I sometimes miss the intended element because some elements might not have loaded.

By cssBy = By.css("CSS_HERE");
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(cssBy);
List<WebElement> tabs = driver.findElements(cssBy);
WebElement element =
        tabs.stream().filter(tab -> tab.getText().contains("TARGET_TEXT")).findAny().get();

the above snippet sometimes misses the indented elements which satisfy the CSS but have not loaded when selenium checked for it. This results in me getting no matching element in second part.

I tried with textMatches and locator

By cssBy = By.css("CSS_HERE");
wait.until(ExpectedConditions.textMatches(cssBy, "TARGET_TEXT");
....

But I think the above snippet is selecting the first element it can find matching CSS and waits for its text to be TARGET_TEXT which is not my intention.

Any suggestions to wait for text match in case of multiple elements matching the locator?

Upvotes: 2

Views: 697

Answers (2)

undetected Selenium
undetected Selenium

Reputation: 193108

Instead of presenceOfAllElementsLocatedBy() you need to induce WebDriverWait for the visibilityOfAllElementsLocatedBy() and you can use the following Locator Strategy:

By cssBy = By.css("CSS_HERE");
wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(cssBy);
List<WebElement> tabs = driver.findElements(cssBy);
WebElement element =
    tabs.stream().filter(tab -> tab.getText().contains("TARGET_TEXT")).findAny().get();

Upvotes: 1

Alin Stelian
Alin Stelian

Reputation: 897

You could write your own Expected Conditions method here is an example for textMatches()

  public static ExpectedCondition<List<WebElement>> textMatches(final By locator, final Pattern pattern) {
    return new ExpectedCondition<List<WebElement>>() {
        @Override
        public List<WebElement> apply(WebDriver driver) {
            String currentValue;
            List<WebElement> elements = driver.findElements(locator);
            List<WebElement> matchingElements = new ArrayList();


            for(WebElement element : elements){
                currentValue = element.getText();
                if (pattern.matcher(currentValue).find()){
                    matchingElements.add(element);
                }
            }
            return matchingElements;
        }

        @Override
        public String toString() {
            return "matching elements for  " + locator;
        }
    };
}

Upvotes: 0

Related Questions