2010-03-03 22 views
8

Sto scrivendo i test WatiN per testare un'applicazione web Ajax e ho riscontrato un problema di temporizzazione con le richieste Ajax.Come aspettare che jQuery Ajax richieda il completamento da WatiN?

Dopo che una richiesta Ajax è stata attivata da un'azione sulla pagina, vorrei che WatiN attenda fino al completamento della richiesta prima di confermare che la pagina è stata aggiornata correttamente.

Ho la sensazione che la soluzione includa la valutazione di JavaScript per registrare i gestori per $.ajaxStart e $.ajaxComplete per verificare se le richieste sono in corso. Scoprirò a breve, ma volevo vedere se qualcun altro ha già risolto questo problema. Sembra che sarebbe un problema comune con il test Ajax.

risposta

18

Ho creato alcuni metodi di estensione del browser WatiN per risolvere questo problema, ma sono ancora interessato ad altre soluzioni.

Il metodo InjectAjaxMonitor crea una variabile globale javascript che si collega agli eventi ajaxStart e ajaxComplete per tenere traccia del numero di richieste in corso.

Ogni volta che è necessario attendere il completamento delle richieste AJAX prima di proseguire, è possibile chiamare 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

Questa soluzione funziona bene a meno che una o più richieste di ajax non inizino prima che venga iniettato il javascript del monitor (a quel punto il contatore non è più preciso). Non so come iniettare il monitor in precedenza nel processo da WatiN. Può essere che la soluzione migliore sia quella di includere condizionalmente il monitor subito dopo l'aggiunta di jQuery durante l'esecuzione dei test. –

+0

Inserisco i gestori di eventi globali ajax nella mia pagina principale dell'applicazione. Inoltre tengo solo un semaforo invece di un contatore: http://lebobitz.wordpress.com/2011/03/06/synchronizing-watin-and-ajax-with-jquery/ –

+2

Un problema con il tuo codice però - se il il sito Web non ha il supporto di jQuery (come nel mio caso) - potresti prima volerlo "iniettare". Basta aggiungere questo codice prima dello "script 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 ('testa') [0] .appendChild (element1); "; browser.Eval (jquerry); – Alex

6

Questa soluzione non funziona molto bene perché .ajaxStart viene chiamato solo per la prima richiesta Ajax, mentre .ajaxComplete è chiamata ogni volta che una richiesta AJAX è terminata. se si esegue un questo semplice codice nella console:

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

e aggiungere un po 'di registrazione nei metodi dei gestori .ajaxStart e .ajaxComplete, si può vedere che .ajaxStart gestore viene richiamato solo una volta e .ajaxComplete gestore due volte. Dunque ajaxRequestCount diventerà negativo e tutto il tuo design è fottuto.

Suggerisco di utilizzare .ajaxSend invece di .ajaxStart se si desidera mantenere il proprio design.

Un'altra soluzione sarebbe quella di utilizzare .ajaxStop invece di .ajaxComplete, ma così facendo, non è necessario il ajaxRequestCount, è necessario solo un valore booleano che dicono che se ci sono richieste Ajax in esecuzione dietro la scena.

Informazioni molto utili si possono trovare: http://api.jquery.com/category/ajax/global-ajax-event-handlers/

Spero che questo aiuti.

+0

Buona chiamata sull'uso improprio di .ajaxStart. Questo è un bug nella mia soluzione. Usare .ajaxStop sarebbe anche più semplice. Grazie! –

3

Mi sono imbattuto in questo problema mentre lavoravo su alcuni test che utilizzavano WatiN. Ho trovato che in version 1.1.0.4000 of WatiN (uscito il 2 maggio 2007 (la versione più recente essendo 2.0 RC2 dal 20 dicembre 2009)), si sostiene che un migliore supporto per la gestione Ajax nei test sono stati aggiunti:

Per meglio il test il supporto di AJAX siti Web abilitati, questa versione aggiunge altre opzioni alla casella degli strumenti.

Viene aggiunto un nuovo metodo che attenderà fino a quando alcuni attributi hanno un determinato valore .Ciò potrebbe essere utile nelle situazioni in cui è necessario attendere fino a quando il valore di un elemento diventa aggiornato .

Esempio:

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

Vedere la link to the release notes per ulteriori informazioni.

Non l'ho ancora esaminato nei dettagli, quindi non posso dire in quali casi potrebbe essere utile o meno. Ma ho pensato che potesse valere la pena di menzionarlo nel caso in cui qualcun altro si imbattesse in questa domanda.

Problemi correlati