0

我们希望将一些键发送到由名称标识的元素。在应用程序中可能有多个具有相同名称的元素,但在这种情况下,只有一个是可见的。为此,我们有一个这样的代码片段(简单的代码,没有生产代码):

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

如果标题元素还没有出现,我们使用隐式等待来等待它出现。所以通常这会很好。无论如何,我们有时会遇到这样的情况,即已经存在具有该名称的元素(但被隐藏了),而正确的元素只会由异步代码创建。但在这种情况下,代码将不起作用。由于findElements()将立即返回(没有隐式等待),只返回不可见的元素。在这种情况下,sendKeys()将等待元素变得可见,但这永远不会发生(忽略在 之后创建的新元素findElements),因此它在隐式等待超时后失败。

基本上,我们需要有可能告诉findElements()我们只想拥有可见元素。如果没有可见元素 Selenium 应该等待隐式等待持续时间。这可能吗?

4

2 回答 2

1

由于您的用例涉及:

  • 可能有多个具有相同名称的元素,但在这种情况下,只有一个可见
  • 将一些键发送到由名称标识的元素
  • 等待它出现
  • 使用隐式等待

满足上述所有条件的多用途解决方案是将WebDriverWait与设置为的ExpectedConditionselementToBeClickable()结合使用。

  • 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 秒后发生超时。

您可以在Replace implicit wait with explicit wait (selenium webdriver & java)中找到相关讨论

于 2019-06-19T20:37:08.557 回答
0

根据 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);
});
于 2019-06-19T21:56:00.853 回答