Come aspettare la richiesta di jQuery Ajax per completare da WatiN?

Sto scrivendo test WatiN per testare un’applicazione web Ajax e ho riscontrato un problema di temporizzazione con le richieste Ajax.

Dopo che una richiesta Ajax è stata triggersta 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 $.ajaxStart $.ajaxComplete 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.

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 devi attendere il completamento delle richieste AJAX prima di proseguire, puoi 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 ); } } 

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

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

e aggiungi alcuni metodi di registrazione nei metodi .ajaxStart e .ajaxComplete , puoi vedere che il gestore di .ajaxStart verrà chiamato solo una volta e gestore .ajaxComplete due volte. Quindi ajaxRequestCount diventerà negativo e tutto il tuo design è fottuto.

Ti suggerisco di usare .ajaxSend invece di .ajaxStart se vuoi mantenere il tuo design.

Un’altra soluzione sarebbe usare .ajaxStop invece di .ajaxComplete , ma così facendo non hai bisogno di ajaxRequestCount , hai solo bisogno di un booleano che dica se ci sono richieste ajaxRequestCount esecuzione dietro la scena.

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

Spero che questo ti aiuti.

Mi sono imbattuto in questo problema mentre lavoravo su alcuni test usando WatiN. Ho scoperto che nella versione 1.1.0.4000 di WatiN (rilasciata il 2 maggio 2007 (l’ultima versione è 2.0 RC2 dal 20 dicembre 2009), si afferma che è stato aggiunto un miglior supporto per la gestione di Ajax nei test:

Per supportare meglio i test dei siti Web abilitati AJAX, questa versione aggiunge alcune ulteriori opzioni alla tua casella degli strumenti.

Viene aggiunto un nuovo metodo che attenderà che un determinato attributo abbia un determinato valore. Questo potrebbe essere utile in situazioni in cui è necessario attendere fino all’aggiornamento del valore di un elemento.

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

Vedi il link alle note di rilascio per maggiori 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.