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