ждать.пока (ExpectedConditions.visibilityOf Element1 или Element2)

Я хочу использовать wait.until(ExpectedConditions) с двумя элементами. Я провожу тест, и мне нужно WebDriver ждать, пока либо Element1 и Element2 показывает вверх. Тогда мне нужно забрать того, кто появится первым. Я пробовал:

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();

чтобы подвести итог, мне нужно подождать, пока не появится любой из двух элементов. Затем выберите того, кто появляется (они не могут появиться одновременно) пожалуйста помочь.

7 ответов


к сожалению, такой команды нет. Вы можете преодолеть это, пытаясь поймать, или я бы лучше рекомендовал вам использовать Watij.


теперь есть собственное решение для этого or метод проверьте doc.

вы используете его так:

driverWait.until(ExpectedConditions.or(
    ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.something")),
    ExpectedConditions.presenceOfElementLocated(By.cssSelector("div.anything"))));

это метод, который я объявил в своем вспомогательном классе, он работает как шарм. Просто создайте свой собственный ExpectedCondition и верните любой из элементов, найденных локаторами:

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;
        }
    };
}

и затем вы можете использовать его таким образом:

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)
        )
);

здесь SERVICE_TITLE_LOCATOR и ATTENTION_REQUEST_ALREADY_PRESENTS_WINDOW_LOCATOR два статических указателей на страницы.


Я думаю, что ваша проблема имеет простое решение, если вы поместите "или" в xpath.

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

затем для печати результата используйте, например:

if(driver.findElements(By.xpath("//h2[@class='....']")).size()>0){
       driver.findElement(By.xpath("//h2[@class='....']")).getText();
}else{
       driver.findElement(By.xpath("//h3[@class='....']")).getText();
}

существует альтернативный способ ожидания, но он не использует ожидаемые условия и вместо этого использует лямбда-выражение..

wait.Until(x => driver.FindElements(By.Xpath("//h3[@class='... ']")).Count > 0 || driver.FindElements(By.Xpath("//h2[@class='... ']")).Count > 0); 

вы также можете использовать CSSSelector следующим образом:

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

замените someClass и otherClass тем, что у вас было в [...] в xpath.


есть простое решение для этого, используя явную ожидания:

wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[@id='FirstElement' or @id='SecondElement']")));

до этого я пытался использовать wait.until(ExpectedConditions.or(..., который не был совместим с версиями selenium до 2.53.0.