【问题标题】:Wait for an Ajax call to complete with Selenium 2 WebDriver使用 Selenium 2 WebDriver 等待 Ajax 调用完成
【发布时间】:2011-09-06 06:47:55
【问题描述】:

我正在使用 Selenium 2 WebDriver 来测试使用 AJAX 的 UI。

有没有办法让驱动程序等待 Ajax 请求完成。

基本上我有这个:

d.FindElement(By.XPath("//div[8]/div[3]/div/button")).Click();
// This click trigger an ajax request which will fill the below ID with content.
// So I need to make it wait for a bit.

Assert.IsNotEmpty(d.FindElement(By.Id("Hobbies")).Text);

【问题讨论】:

  • 这是什么语言?
  • @jcollum 它是 C#

标签: c# ajax selenium selenium-webdriver


【解决方案1】:
var wait = new WebDriverWait(d, TimeSpan.FromSeconds(5));
var element = wait.Until(driver => driver.FindElement(By.Id("Hobbies")));

【讨论】:

  • 你确定是这样吗,因为它没有帮助
  • ajax 调用时间是否超过 5 秒?如果在 5 秒内找不到元素,上面的代码会抛出异常。另外,ajax 调用完成后元素爱好是否可见? WebDriver 只会找到对最终用户可见的元素。
  • @hhastekin ajax 调用是即时的,看起来根本不需要等待,因为可见元素还可以,但是 .Text for style="display:none;"元素给出空
  • @Omu,WebDriver 被设计成只显示真实用户看到的内容。如果用户看不到它,那么 webdriver 也看不到它。
  • @hhastekin 很好,它看到了输入类型的值属性:隐藏
【解决方案2】:

如果您使用 jQuery 处理您的 ajax 请求,您可以等到 jQuery.active 属性为零。其他库可能有类似的选项。

public void WaitForAjax()
{
    while (true) // Handle timeout somewhere
    {
        var ajaxIsComplete = (bool)(driver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
        if (ajaxIsComplete)
            break;
        Thread.Sleep(100);
    }
}

【讨论】:

  • 这是 C#,但该模式也应适用于其他实现。
  • 那么,您是在告诉我,我应该每 100 毫秒检查一次是否已重置?在 jquery 端调用 ajax 成功方法时可以触发它吗?只是在寻找更好的解决方案。
【解决方案3】:

这是我的代码:

public static void WaitForCommission (WebDriver driver) throws Exception {
    for (int second = 0;; second++) {
        if (second >= 30) fail("timeout");
        try { 
            if (IsElementActive(By.id("transferPurposeDDL"), driver)) 
                break; 
            } catch (Exception e) {}
        Thread.sleep(1000);
    }
}

private static boolean IsElementActive(By id, WebDriver driver) {
    WebElement we =  driver.findElement(id);        
    if(we.isEnabled())
        return true;
    return false;
}

这段代码真的很好用。

【讨论】:

    【解决方案4】:

    通过添加超时参数只是一点点改进:

    internal static void WaitForAllAjaxCalls(this ISelenium selenium, IWebDriver driver, int timeout = 40)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            while (true)
            {
                if (sw.Elapsed.Seconds > timeout) throw new Exception("Timeout");
                var ajaxIsComplete = (bool)driver.ExecuteScript("return jQuery.active == 0");
                if (ajaxIsComplete)
                    break;
                Thread.Sleep(100);
            }            
        }
    

    【讨论】:

      【解决方案5】:

      您也可以在此处使用 Selenium 显式等待。那你就不用自己处理超时了

      public void WaitForAjax()
      {
          var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
          wait.Until(d => (bool)(d as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0"));
      }
      

      【讨论】:

      • 有没有办法为不使用 JQuery 的 AJAX 做到这一点?
      • 在不使用 jQuery 时,我找不到通用的方法来执行此操作。似乎每个单独的案例都需要与开发人员一起解决。
      • 请注意,WebDriverWait 需要 Selenium.Support NuGet 包。
      【解决方案6】:

      基于 Morten Christiansens 答案的 Java 解决方案

      公共 void WaitForAjax() 抛出 InterruptedException { 而(真) { Boolean ajaxIsComplete = (Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0"); 如果(ajaxIsComplete){ 休息; } 线程.sleep(100); } }

      【讨论】:

        【解决方案7】:

        只是小小的改进:

        //Wait for Ajax call to complete
          public void WaitForAjax1() throws InterruptedException
            {
        
                while (true)
                {
                    if ((Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")){
                        break;
                    }
                    Thread.sleep(100);
                }
            }
        

        【讨论】:

          【解决方案8】:

          如果你使用Graphene,你可以使用这个:

          Graphene.waitModel().until((Predicate<WebDriver>) input -> (Boolean) ((JavascriptExecutor) input).executeScript("return jQuery.active == 0"));
          

          【讨论】:

            【解决方案9】:

            “XML Http 请求”是用于向服务器发送 Ajax 请求的协议,因此此类请求的存在表明正在进行基于 Ajax 的操作。

            有许多浏览器插件允许您监控浏览器发送的 XML Http 请求。我个人使用 Firefox 的 Firebug 插件,这是一个非常有用的工具。安装后 Firebug 会在浏览器窗口的右下角显示一个类似 Bug 的图标。单击类似 bug 的图标会启动 Firebug,如上图所示。选择“Net”,然后选择“XHR”以启动 XHR 控制台,其中将显示浏览器发送的所有 XML HTTP 请求。

            尽可能避免使用 thread.sleep()。这是一段代码,它接受等待时间作为输入,并在指定时间运行秒表。

            您可以将输入时间(以秒为单位)设置为 30 开始。

            protected void WaitForAjaxToComplete(int timeoutSecs)
                    {
            
                        var stopWatch = new Stopwatch();
            
                        try
                        {
                            while (stopWatch.Elapsed.TotalSeconds < timeoutSecs)
                            {
            
                                var ajaxIsComplete = (bool)(WebDriver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
                                if (ajaxIsComplete)
                                {
                                    break;
                                }
            
                            }
                        }
                        //Exception Handling
                        catch (Exception ex)
                        {
                            stopWatch.Stop();
                            throw ex;
                        }
                        stopWatch.Stop();
            
                    }
            

            【讨论】:

              【解决方案10】:

              如果你使用Coypu,你可以在AJAX调用后检查一个元素是否存在,然后你可以点击它:

              private void WaitUntilExistsThenClick(string selectorId)
              {
                  var searchBoxExists = new State(() => browser.FindId(selectorId).Exists());
                  if (browser.FindState(searchBoxExists) == searchBoxExists)
                  {                
                      browser.FindId(selectorId).Click();
                  }
              }       
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2018-08-20
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-01-03
                • 2013-10-14
                • 2018-04-11
                相关资源
                最近更新 更多