How to Wait for an AJAX Postback to Complete
Note: As of the 2012 R1 version released in April 2012, this process is rendered obsolete by the AjaxTimeout Test Step Property. PROBLEM
Many websites use
AJAX postbacks
to dynamically update the UI of a web page. There a many advantages to both the web
designer and the user interacting with the website to using AJAX. However it creates
a complication for test automation. How do we synchronize with these postback
events so that our test script doesn't run too fast and start looking for things
that the web server hasn't yet sent to the browser?
SOLUTION
The easiest thing to implement is to wait for a UI element to change. For
example
our grid demo page here uses an AJAX postback event to update the grid with
new data when you click "Add new record". There's a count of the total number of
records located in the bottom right. When you click the checkmark to finish
adding the new record, this count is incremented. To properly synchronize with
this AJAX postback, we simply need to add a "Wait For" step that waits for the
count to be at the right value. For example, if we know it's going from 77 to 78, we wait
for the value to equal 78 as shown in this example:
So what do we do if we don't know what the starting
value is going to be when we
run the test? We use Extraction to get the current value and then we change the "Wait For" step
into a "Wait for TextContent to NotContain the extracted value," as in this example:
The above is great when
you have a known UI element you can count on changing after the AJAX postback is
completed and you can use for test script synchronization. So what do you do if you
don't have a such a UI element? For example you're dealing with a
DataGrid, its content could be anything, and the data could be in any
order. Fortunately in Test Studio there is an easy to implement coded step that you
can use to detect when an AJAX postback operation is underway and wait for it to
complete. First, let's look at the code that waits for the postback to complete.
Wait.For<bool>(c => ActiveAjaxConnections() == false, false, 10000);
ActiveBrowser.RefreshDomTree();
This line of code will wait up to 10 seconds for the function ActiveAjaxConnections()
to return false. After the wait is complete, it refreshes our local cached copy of
the DOM to take into account any changes that were just made by the AJAX postback
(if we don't do this our test will start acting on a stale copy of the browser's
DOM).
The contents of the ActiveAjaxConnections function depends slightly on which
AJAX library your website is using. If using jQuery
use this function definition:
public bool ActiveAjaxConnections()
{
return Actions.InvokeScript<bool>("jQuery.active == 0");
}
If using Microsoft's ASP.NET (which includes
our own RadControls for
ASP.NET AJAX) use this function definition:
public bool ActiveAjaxConnections()
{
return Actions.InvokeScript<bool>("Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack()");
}
If using Prototype use this function
definition:
public bool ActiveAjaxConnections()
{
return Actions.InvokeScript<bool>("Ajax.activeRequestCount == 0");
}
If using Dojo use this function definition:
public bool ActiveAjaxConnections()
{
return Actions.InvokeScript<bool>("dojo.io.XMLHTTPTransport.inFlight.length == 0");
}