【问题标题】:Selenium: Waiting for an element do disappear硒:等待一个元素确实消失
【发布时间】:2021-01-27 14:54:43
【问题描述】:

我提出了一项艰巨的任务。我对 selenium 还很陌生,并且仍在使用等待元素等功能。

我必须在一个网站上处理一些数据,然后再转到另一个。问题:操作调用了一个脚本,该脚本在后台处理被操作的数据时会出现一个小的“正在保存...”标签。我必须等到我可以进入下一个网站。

所以这里是: 我如何等待元素消失?问题是:它始终存在于 DOM 中,但只能通过某些脚本可见(我想,见下图)。

这是我尝试过的,但它不起作用 - 没有等待,selenium 只是继续下一步(并且卡住了一个警报,询问我是要离开还是留在页面上,因为“保存...”)。

private By savingLableLocator = By.id("lblOrderHeaderSaving");

    public boolean waitForSavingDone(By webelementLocator, Integer seconds){
    WebDriverWait wait = new WebDriverWait(driver, seconds);
    Boolean element = wait.until(ExpectedConditions.invisibilityOfElementLocated(webelementLocator));
    return element;
}

更新/解决方案:

我想出了以下解决方案:我构建了自己的方法。基本上它会在一个循环中检查 CssValue 的变化。

循环检查 CSSVALUE“显示”从“阻塞”到另一个状态的特定时间。

public void waitForSavingOrderHeaderDone(Integer _seconds){
    WebElement savingLbl = driver.findElement(By.id("lblOrderHeaderSaving"));   
    for (int second = 0;; second++) {
        if (second >= _seconds)
            System.out.println("Waiting for changes to be saved...");
        try {
            if (!("block".equals(savingLbl.getCssValue("display"))))
                break;
        } catch (Exception e) {

        }
    }

【问题讨论】:

标签: java selenium wait invisible


【解决方案1】:

您可以像这样等待 WebElement 抛出 StaleElementReferenceException:

public void waitForInvisibility(WebElement webElement, int maxSeconds) {
    Long startTime = System.currentTimeMillis();
    try {
        while (System.currentTimeMillis() - startTime < maxSeconds * 1000 && webElement.isDisplayed()) {}
    } catch (StaleElementReferenceException e) {
        return;
    }
}

因此,您将传入要等待的 WebElement,以及要等待的最大秒数。

【讨论】:

    【解决方案2】:

    Webdriver 内置了等待功能,您只需要构建等待的条件即可。

    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
       .withTimeout(30, SECONDS)
       .pollingEvery(5, SECONDS)
       .ignoring(NoSuchElementException.class);
    
    WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
     public WebElement apply(WebDriver driver) {
       return (driver.findElements(By.id("lblOrderHeaderSaving")).size() == 0);
     }
    });
    

    【讨论】:

    • IDE (Eclipse) 希望我将 Webelement foo 的返回类型更改为 boolean - 为什么?它告诉我将“public WebElement apply(WebDriver driver) {...”更改为“public boolean apply(WebDriver driver) {...”来自 IDE 的提示:“无法从布尔值转换为 WebElement”
    • @christoph-zabinski 如果您更改建议(第二条语句WebElement...)@nguyen-vu-hoang 会起作用:WebElement foo = wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("lblOrderHeaderSaving")));
    【解决方案3】:

    我不确定,但你可以尝试这样的事情:)

    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //time in second
    WebElement we = driver.findElement(By.id("lblOrderHeaderSaving"));   
    assertEquals("none", we.getCssValue("display"));
    

    【讨论】:

    • 最终这就是我为提出解决方案所做的事情。关键是使用 CssValue 并在循环中检查它的状态。然后继续。
    【解决方案4】:

    这适用于 selenium 2.4.0。你必须使用隐形方法才能找到它。

    final public static boolean waitForElToBeRemove(WebDriver driver, final By by) {
        try {
            driver.manage().timeouts()
                    .implicitlyWait(0, TimeUnit.SECONDS);
    
            WebDriverWait wait = new WebDriverWait(UITestBase.driver,
                    DEFAULT_TIMEOUT);
    
            boolean present = wait
                    .ignoring(StaleElementReferenceException.class)
                    .ignoring(NoSuchElementException.class)
                    .until(ExpectedConditions.invisibilityOfElementLocated(by));
    
            return present;
        } catch (Exception e) {
            return false;
        } finally {
            driver.manage().timeouts()
                    .implicitlyWait(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        }
    }
    

    【讨论】:

      【解决方案5】:

      我使用以下 C# 代码来处理这个,你可以将它转换为 Java

          public bool WaitForElementDisapper(By element)
          {
              try
              {
                  while (true)
                  {
                      try
                      {
                          if (driver.FindElement(element).Displayed)
                              Thread.Sleep(2000);
                      }
                      catch (NoSuchElementException)
                      {
                          break;
                      }
                  }
                  return true;
              }
              catch (Exception e)
              {
                  logger.Error(e.Message);
                  return false;
              }
          }
      

      【讨论】:

        【解决方案6】:

        您也可以尝试等待 ajax 调用完成。我用它来检查页面加载何时完成并且所有元素都可见。

        这是代码 - https://stackoverflow.com/a/46640938/4418897

        【讨论】:

          【解决方案7】:

          您可以使用 XPath 和 WebDriverWait 来检查 display: none 是否存在于元素的样式属性中。这是一个例子:

          // Specify the time in seconds the driver should wait while searching for an element which is not present yet.
          int WAITING_TIME = 10;
          
          // Use the driver for the browser you want to use.
          ChromeDriver driver = new ChromeDriver();
          WebDriverWait wait = new WebDriverWait(driver, WAITING_TIME);
          
          // Replace ELEMENT_ID with the ID of the element which should disappear. 
          // Waits unit style="display: none;" is present in the element, which means the element is not visible anymore.
          driver.wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[@id='ELEMENT_ID'][contains(@style, 'display: block')]")));
          

          【讨论】:

            【解决方案8】:

            尝试使用invisibilityOfElementLocated 方法。 你可以参考这里的例子How to wait until an element no longer exists in Selenium?

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-12-08
              • 2018-02-02
              • 1970-01-01
              • 1970-01-01
              • 2018-07-31
              • 2016-07-28
              相关资源
              最近更新 更多