Selenium: пусть findElements ждет видимого элемента, хотя невидимый элемент существует - PullRequest
0 голосов
/ 19 июня 2019

Мы хотим отправить некоторые ключи элементу, идентифицированному по имени.В приложении может быть несколько элементов с одинаковым именем, но в этом случае будет виден только один элемент.Для этого у нас есть такой фрагмент кода (упрощенный код, без производственного кода):

List<WebElement> list = driver.findElements(By.xpath("//[@name='title']"));
for (WebElement elem : list) {
    try {
         elem.sendKeys(value);
         break;
    } catch (Exception e) {
         // ignore
    }
}

Если элемент title еще не существует, мы ожидаем его появления с использованием неявного ожидания.Так что обычно это будет работать нормально.В любом случае, иногда мы имеем дело с тем, что уже есть элементы с таким именем (но они скрыты), и правильный будет просто создан асинхронным кодом.Но в этом случае код не будет работать.Поскольку findElements() вернется немедленно (без неявного ожидания), просто вернув невидимые элементы.В этом случае sendKeys() будет ждать, пока элемент станет видимым, но этого никогда не произойдет (игнорируя новые элементы, созданные после findElements), и поэтому произойдет сбой после неявного тайм-аута ожидания.

В основном нам нужна возможностьскажите findElements(), что мы просто хотим иметь видимые элементы.Если видимых элементов нет, Selenium должен дождаться неявного ожидания.Это возможно?

Ответы [ 2 ]

0 голосов
/ 20 июня 2019

На основании ответа от DebanjanB и JeffC я смог создать свою собственную реализацию ожидания, которая ожидает первый видимый элемент, но также учитывает элементы, созданные во время ожидания:

new WebDriverWait(driver, 5).until(drv -> {
    List<WebElement> elements = drv.findElements(By.xpath("//[@name='title']"));
    for (WebElement element : elements) {
        if (element.isDisplayed()) {
            return element;
        }
    }
    return null;
});

Илис потоками; -)

new WebDriverWait(driver, 5).until(drv -> {
    List<WebElement> elements = drv.findElements(By.xpath("//[@name='title']"));
    return elements.stream()
        .filter(WebElement::isDisplayed)
        .findFirst()
        .orElse(null);
});
0 голосов
/ 19 июня 2019

Поскольку ваш сценарий использования включает в себя:

  • может быть несколько элементов с одинаковым именем, но в этом случае будет виден только один
  • отправить некоторые ключи элементу, идентифицированному по имени
  • , дождаться его появления
  • , используя неявное ожидание

Многоцелевым решением для удовлетворения всех вышеупомянутых условий будет использование WebDriverWait в сочетании с ExpectedConditions , установленным как elementToBeClickable().

  • elementToBeClickable(): ожидание проверки элемента отображается и активируется таким образом, что вы можете щелкнуть по нему.

  • Пример кода:

    try {
        new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//button[@class='nsg-button']"))).sendKeys(value);
    }
    catch (TimeoutException e) {
        System.out.println("Desired element was not present");
    }
    

Кроме того, необходимо удалить все экземпляры ImplicitWait

Примечание : Не смешивать implicit and explicit waits.Это может привести к unpredictable wait times.Например, установка неявного ожидания 10 секунд и явного ожидания 15 секунд может привести к возникновению тайм-аута через 20 секунд.

Соответствующее обсуждение можно найти в Заменить неявное ожидание наявное ожидание (селен вебдрайвер и Java)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...