2010-03-03 70 views
8

我在寫WatiN測試以測試Ajax Web應用程序,並且遇到了Ajax請求的時間問題。如何等待從WatiN完成的jQuery Ajax請求?

在頁面上的操作觸發Ajax請求之後,我想WatiN等待請求完成,然後驗證頁面是否已正確更新。

我有一種感覺,該解決方案將涉及評估JavaScript註冊處理程序爲$.ajaxStart$.ajaxComplete來跟蹤請求是否正在進行。我很快就會深究,但是想看看其他人是否已經解決了這個問題。似乎這將是Ajax測試的常見問題。

回答

18

我已經創建了幾個WatiN瀏覽器擴展方法來解決這個問題,但我仍然對其他解決方案感興趣。

InjectAjaxMonitor方法創建一個JavaScript全局變量,該變量附加到ajaxStart和ajaxComplete事件以跟蹤正在進行的請求數。

無論何時您需要等待AJAX​​請求完成後才能繼續,您可以致電browserInstance.WaitForAjaxRequest();


public static class BrowserExtensions 
{ 
    public static void WaitForAjaxRequest(this Browser browser) 
    { 
     int timeWaitedInMilliseconds = 0; 
     var maxWaitTimeInMilliseconds = Settings.WaitForCompleteTimeOut*1000; 

     while (browser.IsAjaxRequestInProgress() 
       && timeWaitedInMilliseconds < maxWaitTimeInMilliseconds) 
     { 
      Thread.Sleep(Settings.SleepTime); 
      timeWaitedInMilliseconds += Settings.SleepTime; 
     } 
    } 

    public static bool IsAjaxRequestInProgress(this Browser browser) 
    { 
     var evalResult = browser.Eval("watinAjaxMonitor.isRequestInProgress()"); 
     return evalResult == "true"; 
    } 

    public static void InjectAjaxMonitor(this Browser browser) 
    { 
     const string monitorScript = 
      @"function AjaxMonitor(){" 
      + "var ajaxRequestCount = 0;" 

      + "$(document).ajaxSend(function(){" 
      + " ajaxRequestCount++;" 
      + "});" 

      + "$(document).ajaxComplete(function(){" 
      + " ajaxRequestCount--;" 
      + "});" 

      + "this.isRequestInProgress = function(){" 
      + " return (ajaxRequestCount > 0);" 
      + "};" 
      + "}" 

      + "var watinAjaxMonitor = new AjaxMonitor();"; 

     browser.Eval(monitorScript); 
    } 
} 
+1

該解決方案運行良好,除非在注入監視器javascript之前開始一個或多個ajax請求(此時計數器不再準確)。 我不知道如何在WatiN的過程中提前注入顯示器。最好的辦法是在運行測試時包含jquery後立即包含監視器。 – 2010-03-09 22:47:36

+0

我將全局ajax事件處理程序放入我的應用程序的主頁面中。此外,我只保留一個semaphone位,而不是一個計數器:http://lebobitz.wordpress.com/2011/03/06/synchronizing-watin-and-ajax-with-jquery/ – 2011-03-11 03:16:54

+2

您的代碼雖然有一個問題 - 如果網站沒有jQuery支持(就像我的情況) - 你可能想先「注入」它。只需在「監視器腳本」之前添加此代碼即可。 const string jquerry = @「var element1 = document.createElement('script'); element1.src ='http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js'; element1.type = '文本/ JavaScript的'; document.getElementsByTagName( '頭')[0] .appendChild(元素1);「; browser.Eval(jquerry); – Alex 2012-08-27 15:47:22

6

因爲.ajaxStart被稱爲僅第一個Ajax請求該解決方案並不能很好地工作,而.ajaxComplete是每一個Ajax請求完成時調用。如果您在控制檯中運行這個簡單的代碼:

$.ajax({url:"/"}); $.ajax({url:"/"}) 

,並在.ajaxStart.ajaxComplete處理方法添加一些日誌,你可以看到.ajaxStart處理器將只有一次,.ajaxComplete處理程序調用兩次。所以ajaxRequestCount將成爲負面的,你所有的設計都搞砸了。

如果你想保留你的設計,我建議你使用.ajaxSend而不是.ajaxStart

另一種解決方案是使用.ajaxStop代替.ajaxComplete,但這樣做,你不需要ajaxRequestCount,你只需要一個布爾值,它說,如果有運行中的幕後Ajax請求。

非常有用的信息,可以發現:http://api.jquery.com/category/ajax/global-ajax-event-handlers/

希望這有助於。

+0

好的調用濫用.ajaxStart。這是我解決方案中的一個錯誤。使用.ajaxStop也會更簡單。謝謝! – 2010-12-14 19:58:13

3

我剛剛在使用WatiN進行一些測試時遇到了這個問題。我發現,它被要求加在測試中處理Ajax的更好的支持,在version 1.1.0.4000 of WatiN(5月2日2007年發佈(最新版本從2009年12月20日)是2.0 RC2):

阿賈克斯 更好的支撐性測試這個版本增加了 一些更多的選擇到你的工具箱。

添加了一個新方法,它將等待 ,直到某個屬性具有某個 值。這可能在 需要等待 直到元素值更新爲 的情況下得心應手。

實施例:

// Wait until some textfield is enabled 
textfield.WaitUntil("disable", false.ToSting, 10); 
// Wait until some textfield is visible and enabled 
textfield.WaitUntil(new Attribute("visibile", new BoolComparer(true)) && new Attribute("disabled", new BoolComparer(false))); 

更多信息,請參見link to the release notes

我還沒有仔細研究過它,所以我不能告訴它在哪些情況下可能有用或沒有。但認爲如果有其他人遇到這個問題,可以值得一提。