等待Ajax调用以完成Selenium 2 WebDriver

时间:2011-06-01 12:52:08

标签: ajax selenium selenium-webdriver

我正在使用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);

10 个答案:

答案 0 :(得分:76)

如果您正在为ajax请求使用jQuery,则可以等到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);
    }
}

答案 1 :(得分:40)

你也可以在这里使用Selenium显式等待。那么你不需要自己处理超时

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

答案 2 :(得分:15)

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

答案 3 :(得分:6)

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

    public void WaitForAjax() throws InterruptedException
    {

        while (true)
        {

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


答案 4 :(得分: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);
        }            
    }

答案 5 :(得分: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;
}

此代码确实有用。

答案 6 :(得分:2)

只是小改进:

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

答案 7 :(得分:1)

如果您使用Graphene,可以使用此功能:

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

答案 8 :(得分:1)

“XML Http Request”是用于向服务器发送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();

        }

答案 9 :(得分:1)

如果使用Coypu,则可以在AJAX调用后检查元素是否存在,然后可以单击它:

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