wait.until(ExpectedConditions.visibilityOf Element

2020-02-08 19:58发布

I want use wait.until(ExpectedConditions) with TWO elements. I am running a test, and I need WebDriver to wait until either of Element1 OR Element2 shows up. Then I need to pick whoever shows up first. I've tried:

WebDriverWait wait = new WebDriverWait(driver, 60); 
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//h2[@class='....']"))) || wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//h3[@class='... ']"))); 

        // Then I would need:

String result = driver.findElement(By.xpath("...")).getText() || driver.findElement(By.xpath("...")).getText();

To sum up, I need to wait until either of the TWO elements shows up. Then pick whoever shows up (they cannot show up simultaneously) Please Help.

标签: java selenium
7条回答
我想做一个坏孩纸
2楼-- · 2020-02-08 20:42

You can also use a CSSSelector like this:

wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("h2.someClass, h3.otherClass")));

Replace someClass and otherClass with what you had in [...] in the xpath.

查看更多
唯我独甜
3楼-- · 2020-02-08 20:47

I think that your problem has a simple solution if you put "OR" into xpath.

WebDriverWait wait = new WebDriverWait(driver, 60); 
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//h2[@class='....'] | //h3[@class='... ']"))); 

Then, to print the result use for example:

if(driver.findElements(By.xpath("//h2[@class='....']")).size()>0){
       driver.findElement(By.xpath("//h2[@class='....']")).getText();
}else{
       driver.findElement(By.xpath("//h3[@class='....']")).getText();
}
查看更多
Explosion°爆炸
4楼-- · 2020-02-08 20:49

Unfortunately, there is no such a command. You can overcome this by try and catch, or I would better recommend you to use open source Ruby library Watir.

查看更多
看我几分像从前
5楼-- · 2020-02-08 20:50

Now there's a native solution for that, the or method, check the doc.

You use it like so:

driverWait.until(ExpectedConditions.or(
    ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.something")),
    ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.anything"))));
查看更多
\"骚年 ilove
6楼-- · 2020-02-08 20:54

There is an alternative way to wait but it isnt using expected conditions and it uses a lambda expression instead..

wait.Until(x => driver.FindElements(By.Xpath("//h3[@class='... ']")).Count > 0 || driver.FindElements(By.Xpath("//h2[@class='... ']")).Count > 0); 
查看更多
放我归山
7楼-- · 2020-02-08 20:55

This is the method I declared in my Helper class, it works like a charm. Just create your own ExpectedCondition and make it return any of elements found by locators:

public static ExpectedCondition<WebElement> oneOfElementsLocatedVisible(By... args)
{
    final List<By> byes = Arrays.asList(args);
    return new ExpectedCondition<WebElement>()
    {
        @Override
        public Boolean apply(WebDriver driver)
        {
            for (By by : byes)
            {
                WebElement el;
                try {el = driver.findElement(by);} catch (Exception r) {continue;}
                if (el.isDisplayed()) return el;
            }
            return false;
        }
    };
}

And then you can use it this way:

Wait wait = new WebDriverWait(driver, Timeouts.WAIT_FOR_PAGE_TO_LOAD_TIMEOUT);
WebElement webElement = (WebElement) wait.until(
        Helper.oneOfElementsLocatedVisible(
                By.xpath(SERVICE_TITLE_LOCATOR), 
                By.xpath(ATTENTION_REQUEST_ALREADY_PRESENTS_WINDOW_LOCATOR)
        )
);

Here SERVICE_TITLE_LOCATOR and ATTENTION_REQUEST_ALREADY_PRESENTS_WINDOW_LOCATOR are two static locators for page.

查看更多
登录 后发表回答