如何等到 Selenium 中不再存在元素

Posted

技术标签:

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

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

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

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

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

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

【问题讨论】:

【参考方案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 中,而只是不可见

以上是关于如何等到 Selenium 中不再存在元素的主要内容,如果未能解决你的问题,请参考以下文章

Python Selenium:等到元素不再陈旧?

如何等到硒中存在元素?

Selenium - 等到元素存在、可见且可交互,即使在 C# 中的可滚动模式上也是如此

Selenium C# WebDriver:等到元素出现

Python Selenium 2 API 并等待 DOM 准备好/元素可见

sele nium 模块