我需要检查页面上某个元素的可见性。

我正在使用(psuedocode)wait.until(ExpectedCondition.visibilityOfElement(locator));

但是,默认的ExpectedCondition仅检查DOM中与定位器匹配的第一个元素。

我的定位器不能足够具体,只能匹配一个元素(这是我被要求自动化的限制,不能更改)。但是,在找到的元素中,任何显示的都是公平的游戏。

因此,我使用自定义的ExpectedCondition,遍历找到的元素,找到显示的任何元素,并返回找到的第一个元素。

代码如下:

public WebElement WaitForElementToBeVisible(WebDriver theDriver, By locator) {
    return new WebDriverWait(theDriver, STANDARD_WAIT_TIME)
            .pollingEvery(1, TimeUnit.SECONDS)
            .withTimeout(5, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class)
            .until((ExpectedCondition<WebElement>) driver -> {
                List<WebElement> els = driver.findElements(locator);
                for (WebElement el : els) {
                    try {
                        if (el.isDisplayed()) {
                            return el;
                        }
                    } catch (StaleElementReferenceException e) {
                        /* Ignore Exception */
                    } catch (NullPointerException e) {
                        System.out.println("NullPointerException thrown");
                    }
                }
                return null;
            });
}


但是,在某些情况下,对el.isDisplayed的调用将引发NullPointerException。我在其他答案中看到,如果元素不在页面上,则将发生这种情况。但是在这种情况下,我知道该元素存在。

我添加了一些日志,告诉我:


该元素存在(实际上,其中有三个)
在所有三个元素上调用isDisplayed
这三个元素都抛出NullPointerException


另外,由于它需要等待5秒钟才能显示该元素,因此我有足够的时间查看和看到,是的,该元素似乎确实已显示。

如果删除catch块,则NullPointerException的堆栈跟踪如下(仅最后一行,因为其他所有内容都是公司特定的,而我的老板不希望我共享它):

java.lang.NullPointerException
        at org.openqa.selenium.remote.RemoteWebElement.isDisplayed(RemoteWebElement.java:323)



该跟踪导致:

public boolean isDisplayed() {
  Object value = execute(DriverCommand.IS_ELEMENT_DISPLAYED, ImmutableMap.of("id", id))
      .getValue();
  try {
    return (Boolean) value;
  } catch (ClassCastException ex) {
    throw new WebDriverException("Returned value cannot be converted to Boolean: " + value, ex);
  }
}


该错误由return语句引发,因此无论出于何种原因,execute命令都将返回null。

我相信这些是pom文件的相关部分:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.10.0</version>
</dependency>
<dependency>
    <groupId>io.github.bonigarcia</groupId>
    <artifactId>webdrivermanager</artifactId>
    <version>3.6.2</version>
</dependency>


任何调试此问题的帮助将不胜感激。

最佳答案

根本问题似乎是ChromeDriver 77版本中的错误。

我正在此上运行的Salesforce正在修改内置AsyncFunction对象的构造函数,这导致所有Selenium的Javascript调用失败,而不仅仅是isDisplayed。

应该在Chrome / ChromeDriver的版本78中修复。

参考错误和答案:
https://bugs.chromium.org/p/chromedriver/issues/detail?id=3103#c6

09-04 21:57