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

Posted

技术标签:

【中文标题】Selenium - 等到元素存在、可见且可交互,即使在 C# 中的可滚动模式上也是如此【英文标题】:Selenium - wait until element is present, visible and interactable even on a scrollable modal in C# 【发布时间】:2021-07-01 01:22:18 【问题描述】:

这里对 python 提出了同样的问题:Selenium - wait until element is present, visible and interactable。然而,答案并未涵盖所有场景。

当我不处于调试模式时,我的实现有时会失败。 我认为等待 ID 是一项微不足道的任务,应该有一个直接的 KISS 实现并且永远不会失败。

    public IWebElement WaitForId(string inputId, bool waitToInteract = false, int index = 0)
    
        IWebElement uiElement = null;
        while (uiElement == null)
        
            var items = WebDriver.FindElements(By.Id(inputId));
            var iteration = 0;
            while (items == null || items.Count < (index + 1) ||
                   (waitToInteract && (!items[index].Enabled || !items[index].Displayed)))
            
                Thread.Sleep(500);
                items = WebDriver.FindElements(By.Id(inputId));
                if (items.Count == 0 && iteration == 10)
                
                    // "still waiting...: " + inputId
                

                if (iteration == 50)
                
                    // "WaitForId not found: " + inputId
                    Debugger.Break(); // if tried too many times, maybe you want to investigate way
                

                iteration++;
            
            uiElement = WebDriver.FindElement(By.Id(inputId));
        
        return uiElement;
    

【问题讨论】:

“我认为等待一个 ID 是一件微不足道的任务......” - 没有什么是容易的。你能edit你的问题来描述你是如何与这个可滚动模式交互的吗? 【参考方案1】:
    public IWebElement GetActiveElement(string id, int allowedTimeout = 20, int retryInterval = 250)
    
      var wait = new DefaultWait<IWebDriver>(_driver)
      
        Timeout = TimeSpan.FromSeconds(allowedTimeout),
        PollingInterval = TimeSpan.FromMilliseconds(retryInterval)
      ;

      return wait.Until(d =>
      
        var element = d.FindElement(By.Id(id));
        return element.Displayed || element.Enabled ? element : throw new NoSuchElementException();
      );

   // Usage would be something like this

GetActiveElement("foo").SendKeys("Bar");

您应该能够创建扩展方法并改为调用扩展

public static class WebDriverExtension
  
    public static IWebElement GetActiveElement(this IWebDriver driver, string id, int allowedTimeout = 20, int retryInterval = 250)
    
      var wait = new DefaultWait<IWebDriver>(driver)
      
        Timeout = TimeSpan.FromSeconds(allowedTimeout),
        PollingInterval = TimeSpan.FromMilliseconds(retryInterval)
      ;

      return wait.Until(d =>
      
        var element = d.FindElement(By.Id(id));
        return element.Displayed || element.Enabled ? element : throw new NoSuchElementException();
      );
    
  

// usage 
_driver.GetActiveElement("foo").SendKeys("bar");

【讨论】:

以上是关于Selenium - 等到元素存在、可见且可交互,即使在 C# 中的可滚动模式上也是如此的主要内容,如果未能解决你的问题,请参考以下文章

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

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

Robotframework:Selenium2Lib:等到(...)关键字

Selenium C# ElementNotVisibleException:元素不可交互,但该元素实际上是可见的

org.openqa.selenium.ElementNotVisibleException:元素当前不可见,因此可能无法与命令持续时间或超时交互:

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