我们想将一些键发送到按名称标识的元素。在应用程序中,可能有多个具有相同名称的元素,但是在那种情况下,只有一个是可见的。为此,我们有一个这样的代码片段(简单的代码,没有生产代码):
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应该等待隐式等待时间。这可能吗?
答案 0 :(得分:0)
您的用例涉及:
为满足上述所有条件的多功能解决方案是将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秒后发生超时。
您可以在Replace implicit wait with explicit wait (selenium webdriver & java)
中找到相关的讨论答案 1 :(得分:0)
基于DebanjanB和JeffC的回答,我能够创建自己的wait实现,该实现等待第一个可见元素,但也考虑了在等待期间创建的元素:
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);
});