【问题标题】:How to wait until an element no longer exists in Selenium如何等到 Selenium 中不再存在元素
【发布时间】:2015-05-18 22:10:04
【问题描述】:

我正在测试用户单击删除按钮和表格条目消失的 UI。因此,我希望能够检查表条目是否不再存在。

我曾尝试使用ExpectedConditions.not() 反转ExpectedConditions.presenceOfElementLocated(),希望这意味着“期望不存在指定元素”。我的代码是这样的:

browser.navigate().to("http://stackoverflow.com");
new WebDriverWait(browser, 1).until(
        ExpectedConditions.not(
                ExpectedConditions.presenceOfElementLocated(By.id("foo"))));

但是,我发现即使这样做,我也会收到由 NoSuchElementException 引起的 TimeoutExpcetion,表示元素“foo”不存在。当然,没有这样的元素是我想要的,但我不希望抛出异常。

那么我怎样才能等到一个元素不再存在呢?如果可能的话,我更喜欢一个不依赖于捕获异常的示例(据我所知,应该为异常行为抛出异常)。

【问题讨论】:

    标签: java selenium selenium-webdriver


    【解决方案1】:

    你也可以使用 -

    new WebDriverWait(driver, 10).until(ExpectedConditions.invisibilityOfElementLocated(locator));
    

    如果您浏览其中的the source,您可以看到NoSuchElementExceptionstaleElementReferenceException 都被处理了。

    /**
       * An expectation for checking that an element is either invisible or not
       * present on the DOM.
       *
       * @param locator used to find the element
       */
      public static ExpectedCondition<Boolean> invisibilityOfElementLocated(
          final By locator) {
        return new ExpectedCondition<Boolean>() {
          @Override
          public Boolean apply(WebDriver driver) {
            try {
              return !(findElement(locator, driver).isDisplayed());
            } catch (NoSuchElementException e) {
              // Returns true because the element is not present in DOM. The
              // try block checks if the element is present but is invisible.
              return true;
            } catch (StaleElementReferenceException e) {
              // Returns true because stale element reference implies that element
              // is no longer visible.
              return true;
            }
          }
    

    【讨论】:

    • 上述代码中出现奇怪的语法错误:语法错误,插入“;”完成 BlockStatements
    【解决方案2】:

    该解决方案仍将依赖于异常处理。这非常好,即使 standard Expected Conditions 依赖于 findElement() 抛出的异常。

    这个想法是创建一个自定义预期条件

      public static ExpectedCondition<Boolean> absenceOfElementLocated(
          final By locator) {
        return new ExpectedCondition<Boolean>() {
          @Override
          public Boolean apply(WebDriver driver) {
            try {
              driver.findElement(locator);
              return false;
            } catch (NoSuchElementException e) {
              return true;
            } catch (StaleElementReferenceException e) {
              return true;
            }
          }
    
          @Override
          public String toString() {
            return "element to not being present: " + locator;
          }
        };
      }
    

    【讨论】:

    • 您的答案效果很好,但我决定接受另一个答案,因为似乎有一个内置版本可以完全满足我的要求。不过,您的回答是一个很好的指导方针!
    • @Thunderforge 谢谢,我知道这个方法。尽管我假设您需要等待 DOM 中不存在的元素而不是变得不可见。无论如何,很高兴它解决了!
    • 我发现该方法还可以处理它在 DOM 中不存在的情况,而不仅仅是在它不可见的情况下。由于前者是我的用例,而我不关心后者,因此它对我有用,并且节省了我自己的工作量。
    【解决方案3】:

    您为什么不简单地找到elements 的大小。如果 element 不存在,我们知道元素的 size 集合将为 0

    if(driver.findElements(By.id("foo").size() > 0 ){
        //It should fail
    }else{
        //pass
    }
    

    【讨论】:

    • 不幸的是,这个解决方案不会等待元素不再存在;它只检查一次。
    • @VivekSingh 的解决方案是不重新发明轮子的最佳 imo,但如果情况略有不同,此解决方案将与预期条件相结合。看起来像这样:(new WebDriverWait(driver, 30)).withMessage("element was still displayed after timeout").until((ExpectedCondition&lt;Boolean&gt;) d -&gt; d.findElements(By.id("foo").size() &gt; 0));
    【解决方案4】:

    我不知道为什么,但 ExpectedConditions.invisibilityOf(element) 是我唯一的工作,而 ExpectedConditions.invisibilityOfElementLocated(By)!ExpectedConditions.presenceOfElementLocated(By) ... 不是。试试吧!

    希望对您有所帮助!

    【讨论】:

      【解决方案5】:
      // pseudo code
      public Fun<driver,webelement> ElemtDisappear(locator)
      {
          webelement element=null;
          iList<webelement> elemt =null;
          return driver=>
          {
          try
          {
          elemt = driver.findelements(By.locator);
          if(elemt.count!=0)
          {
          element=driver.findelement(By.locator);
          }
          }
          catch(Exception e)
          {
          }
          return(elemnt==0)?element:null;
      };
      
      // call function
      public void waitforelemDiappear(driver,locator)
      {
          webdriverwaiter wait = new webdriverwaiter(driver,time);
          try
          {
          wait.until(ElemtDisappear(locator));
          }
          catch(Exception e)
          {
          }
      }
      

      由于 findelement 在元素 unaviability 上引发异常。所以我使用 findelements 实现。请随时根据您的需要更正和使用它。

      【讨论】:

        【解决方案6】:

        我找到了一种解决方法,可以有效地为我解决此问题,使用以下 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;
                }
            }
        

        【讨论】:

          【解决方案7】:

          好消息,它现在已经内置了(我在 2021 年使用 Node.js)

          在给出之前的答案后,elementIsNotVisible 似乎已添加到 until。我正在使用 selenium webdriver 4.0.0-beta.3

          检查一下:

          const timeout = 60 * 1000; // 60 seconds
          const element = await driver.findElement(By.id(elementId));
          
          // this is the important line 
          await driver.wait(until.elementIsNotVisible(element), timeout);
          

          【讨论】:

          • 这个函数的描述是:Creates a condition that will wait for the given element to be in the DOM, yet not visible to the user.这不是大多数人在这里寻找的。我自己,可能还有其他人正在寻找一种方法来断言元素不在 dom 中,而不是在 dom 中,而只是不可见
          猜你喜欢
          • 2018-04-08
          • 2020-12-05
          • 2020-02-11
          • 1970-01-01
          • 2014-05-03
          • 1970-01-01
          • 2014-07-15
          • 2014-06-06
          • 2014-10-05
          相关资源
          最近更新 更多