【问题标题】:WebDriverWait is not waiting for the element I specifyWebDriverWait 不等待我指定的元素
【发布时间】:2019-08-19 09:50:55
【问题描述】:

我试图让我的代码在尝试从元素中获取文本之前等待元素出现。如果我单步执行允许元素时间出现的代码,它会按预期工作,但如果我在没有断点的情况下运行它,等待似乎会被忽略并引发异常。

我不明白为什么它被忽略了?

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
IWebElement message = wait.Until(driver => driver.FindElement(By.ClassName("block-ui-message")));
string messageText = message.Text;

【问题讨论】:

  • 您遇到什么类型的异常?
  • 我收到了NoSuchElementException,但该元素在那里,因为它在缓慢地单步执行代码时工作正常。

标签: c# selenium selenium-chromedriver webdriverwait


【解决方案1】:

作为替代方案,您可以为ElementIsVisible() 诱导WebDriverWait,您可以使用以下Locator Strategy

string messageText = new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until(ExpectedConditions.ElementIsVisible(By.ClassName("block-ui-message"))).GetAttribute("innerHTML");

DotNetSeleniumExtras.WaitHelpersnuget 一起使用:

不太清楚你所说的我需要的具体使用指令到底是什么意思。如果您使用的是 SeleniumExtrasWaitHelpers,您可以使用以下解决方案:

string messageText = new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.ClassName("block-ui-message"))).GetAttribute("innerHTML");

【讨论】:

  • 我试过这个,但遇到了 ExpectedConditions 部分的问题 - 我需要特定的 using 指令吗?
  • @Northers 查看更新的答案并告诉我状态。
  • 我遇到了同样的问题,只是措辞不同 - '名称 SeleniumExtras 在当前上下文中不存在'
  • 看来你在这里搞砸了几件事:1)你开始你的问题 “出现的元素” 2)使用 ExpectedConditions 你谈到 directive 3) 使用 SeleniumExtras.WaitHelpers 你说的是 ...SeleniumExtras 这个名字不存在...。 4) 在您提到的另一个答案中与元素交互。您的确切用户案例是什么?您尝试自动化手动步骤是什么?
  • 好的,我只需要等到一个元素在屏幕上可见,我就可以与之交互,在这种情况下,我需要从元素中提取文本。该元素最终确实出现在屏幕上,如果我逐步执行,我可以很容易地获得文本,我只需要代码等待直到对象以我可以与之交互的方式出现,这样它就可以在没有我的情况下运行逐步通过它。
【解决方案2】:

下面的示例代码将等到元素出现

        private bool IsElementPresent(By by)
        {
            try
            {
                _driver.FindElement(by);
                return true;
            }
            catch (NoSuchElementException)
            {
                return false;
            }
        }

        private void WaitForReady(By by)
        {
            var wait = new WebDriverWait(_driver, TimeSpan.FromHours(2));
            wait.Until(driver =>
            {
                //bool isAjaxFinished = (bool)((IJavaScriptExecutor)driver).ExecuteScript("return jQuery.active == 0");
                return IsElementPresent(by);
            });
        }

      // ...
      // Usage
      WaitForReady(By.ClassName("block-ui-message")); // It will wait until element which class name is 'block-ui-message' is presented to page

【讨论】:

  • 这种方法很好用,谢谢。你知道为什么我的方法不起作用吗?
  • @Northers 当您通过 lambda 函数创建自己的 ExpectedCondition 时,它以不同的方式工作。在您的情况下,Selenium 期望 IWebElementnull。但是,它得到了NoSuchElementException。如果您只是像 SuxrobGM 那样将代码放入 try-catch 块中,它会起作用
  • 好吧,我的反应还为时过早——使用上面的代码不再给我一个异常,并且确实等待元素出现,但只出现在 DOM 中,所以我无法与当时的元素。 FindElement 是否有替代方法可以确保代码等待元素在屏幕上实际可见并因此允许交互?
  • 使用异步方法。更改上面的代码并实现async/await 方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多