2010-03-03 11 views
8

Estoy escribiendo WatiN pruebas para probar una aplicación web Ajax y he encontrado un problema de tiempo con las solicitudes de Ajax.¿Cómo esperar las solicitudes jQuery Ajax para completar desde WatiN?

Después de que se active una solicitud Ajax por una acción en la página, me gustaría que WatiN espere hasta que se complete la solicitud antes de validar que la página se actualizó correctamente.

Tengo la sensación de que la solución implicará eval-ing JavaScript a registrar manejadores de $.ajaxStart y $.ajaxComplete para rastrear si las solicitudes están en curso. Voy a profundizar en eso en breve, pero quería ver si alguien más ya ha resuelto esto. Parece que sería un problema común con las pruebas de Ajax.

Respuesta

18

He creado algunos métodos de extensión del navegador WatiN para resolver este problema, pero todavía estoy interesado en otras soluciones.

El método InjectAjaxMonitor crea una variable global javascript que se adjunta a los eventos ajaxStart y ajaxComplete para rastrear el número de solicitudes en progreso.

Cuando necesite esperar que las solicitudes AJAX se completen antes de continuar, puede llamar al 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

Esta solución funciona bien a menos que una o más solicitudes ajax comiencen antes de que se instale el monitor javascript (en cuyo momento el contador ya no es preciso). No sé cómo inyectar el monitor antes en el proceso de WatiN. Es posible que la mejor opción sea incluir condicionalmente el monitor justo después de incluir jquery cuando se ejecutan las pruebas. –

+0

Puse los controladores de eventos ajax globales en la página maestra de mi aplicación. También solo conservo un bit de semaphone en lugar de un contador: http://lebobitz.wordpress.com/2011/03/06/synchronizing-watin-and-ajax-with-jquery/ –

+2

Sin embargo, hay un problema con el código: si el sitio web no tiene soporte jQuery (como en mi caso) - es posible que desee "inyectarlo" primero. Simplemente agregue este código antes de la "secuencia de comandos del monitor". 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 = 'text/javascript'; document.getElementsByTagName ('head') [0] .appendChild (element1); "; browser.Eval (jquerry); – Alex

6

Esta solución no funciona muy bien porque .ajaxStart se llama sólo para la primera petición Ajax, mientras que .ajaxComplete se llama cada vez que una petición AJAX está terminado. si se ejecuta un código de este simple en su consola:

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

y añadir un poco de la tala en los métodos de controlador de .ajaxStart y .ajaxComplete, se puede ver que .ajaxStart manejador será llamado una sola vez y dos veces .ajaxComplete manejador. Entonces ajaxRequestCount se volverá negativo y todo su diseño se atornillará.

Sugiero que utilice .ajaxSend en lugar de .ajaxStart si desea mantener su diseño.

Otra solución sería utilizar .ajaxStop en lugar de .ajaxComplete, pero al hacerlo, no es necesario el ajaxRequestCount, sólo es necesario un booleano que dicen que si hay peticiones ajax corriendo detrás de la escena.

información muy útil se puede encontrar: http://api.jquery.com/category/ajax/global-ajax-event-handlers/

Espero que esto ayude.

+0

Buena llamada sobre el uso indebido de .ajaxStart. Eso es un error en mi solución. Usar .ajaxStop sería más simple también. ¡Gracias! –

3

Acabo de toparme con este problema yo mismo mientras trabajo en algunas pruebas usando WatiN. He descubierto que en version 1.1.0.4000 of WatiN (lanzado el 2 de mayo de 2007 (versión más reciente siendo 2.0 RC2 del 20 de diciembre de 2009)), se afirma que un mejor soporte para el manejo de Ajax en las pruebas se añadieron:

Para mejores pruebas de soporte de AJAX sitios habilitados, esta versión agrega algunas opciones más a su caja de herramientas. Se ha agregado un nuevo método que esperará hasta que algún atributo tenga un cierto valor de .Esto podría ser útil en situaciones donde debe esperar hasta que se actualice el valor de un elemento .

Ejemplo:

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

Véase el link to the release notes para más información.

No lo he estudiado en detalle aún, así que no puedo decir en qué casos podría ser útil o no. Pero pensé que podría valer la pena mencionarlo en caso de que alguien más se encuentre con esta pregunta.

Cuestiones relacionadas