2011-06-01 112 views
40

我使用硒2 Web驱动程序来测试使用AJAX的用户界面。等待ajax调用完成与硒2网络驱动程序

有没有办法让司机等候一下,让Ajax请求将完成

基本上我有这样的:

d.FindElement(By.XPath("//div[8]/div[3]/div/button")).Click(); 
// this^ click triggers 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); 

回答

14
var wait = new WebDriverWait(d, TimeSpan.FromSeconds(5)); 
var element = wait.Until(driver => driver.FindElement(By.Id("Hobbies"))); 
+1

你确定这是方法的辩论,因为它并没有帮助 – Omu 2011-06-01 14:12:58

+0

是否Ajax调用需要超过5秒长?如果上面的代码在5秒内找不到该元素,则会引发异常。另外,ajax调用完成后,元素的爱好是否可见? WebDriver只会查找对最终用户可见的元素。 – 2011-06-01 14:22:58

+0

@hhastekin ajax调用是即时的,它看起来好像根本不需要等待,因为可见元素是可以的,但是对于style =“display:none;”来说。元素给出了空的 – Omu 2011-06-02 06:53:21

63

如果你正在使用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); 
    } 
} 
+4

解决了我糟糕的'sleep's :-) – 2012-02-14 12:27:38

+0

这是什么语言? – 2013-01-29 13:12:30

+0

这是C#,但该模式也应该适用于其他实现。 – 2013-02-04 22:06:49

2

这里是我的代码:

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; 
} 

此代码是真正的工作。

3

刚有点起色通过添加一个超时参数:

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); 
     }    
    } 
34

你也可以在这里使用的硒明确的等待。那么你就需要处理超时自己

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

有没有办法为不使用JQuery的AJAX做这件事? – Merkidemis 2014-05-08 18:19:48

+0

没有使用jQuery时,我无法找到通用的方法。似乎需要与开发人员一起解决每个单独的案例。 – Mila 2014-12-03 15:10:53

+0

请注意,WebDriverWait需要Selenium.Support NuGet包。 – ReinierDG 2015-09-02 16:32:39

4

Java解决方案基于莫滕Christiansens回答

 
    public void WaitForAjax() throws InterruptedException 
    { 

     while (true) 
     { 

      Boolean ajaxIsComplete = (Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0"); 
      if (ajaxIsComplete){ 
       break; 
      } 
      Thread.sleep(100); 
     } 
    } 


2
Just small improvement 

//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); 
     } 
    } 
1

如果您正在使用Graphene您可以使用此:

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

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

有许多浏览器插件允许您监视浏览器发送的XML Http请求。我个人使用Firefox的Firebug插件,这是一个非常有用的工具。安装完成后,Firebug会在浏览器窗口的右下角显示一个类似Bug的图标。点击类似bug的图标启动Firebug,如上图所示。选择“网络”,然后选择“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(); 

     }