Update: The javascript on this blog has been suppressed by the blogger's parser. Consequently, some of the functionality may not work. Inconvenience is regretted.

Thursday, April 3, 2008

AJAX Issues With WATIN

Recently I started Automating the UI test cases for our AJAX enabled asp.net website with Watin. It was not long before that I ran into problems as Watin seems to be ajax postback agnostic.

I had a master dropdownlist and a child dropdownlist (this is disabled until something is selected in the master DDL). On the selection of an item in the master DDL there is an AJAX postback that would get data for the child DDL and then an item in the child DDL will be selected. To automate this scenario I wrote the following code:


IE ie = new IE("http://localhost/MySite/Default.aspx");
SelectList ddlMaster = ie.SelectList("ddlMaster");
ddlMaster.Option(Find.ByValue("India")).Select();
SelectList ddlChild = ie.SelectList("ddlChild");
ddlChild.Option(Find.ByValue("Hyderabad")).Select();


The Problem: The first DDL gets selected perfectly and an asynchronous postback happens but I get an exception in the fourth line (which tries to select a value in the child DDL) saying "Could not find OPTION element tag matching criteria: Attribute 'value' with value 'Hyderabad'". The problem was clear - we are trying to select a value in the child DDL before asynchronous postback is over and the child DDL is populated with values.

The first thought that came into my mind was to put a Thread.Sleep but I know it wasn't a good solution since I can never be sure of how long the asynchronous request is going to take. So I looked for something that could tell me if page is still in async postback. Enter the PageRequestManager Class in asp.net ajax. It has a property called isInAsyncPostback that you can query to know if page is in async postback. So all I needed was a way to run some javascript from the code and thank god, there is Eval in Watin to do just that.

The Solution:

1)Updated the aspx page with a method to return true if page is in async postback as below:


<asp:ScriptManager ID="scrptMgr" runat="server" EnablePartialRendering="true">
</asp:ScriptManager> <!-- script manager shown for completeness -->
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
function IsPageInAsyncPostback(){
return prm.get_isInAsyncPostBack();
}

</script>

2) Wrote a helper method to wait until async postback is complete:


private static void WaitForAsyncPostBackToComplete(IE ie)
{
bool isInPostback = true;
while (isInPostback)
{
isInPostback = Convert.ToBoolean(ie.Eval("IsPageInAsyncPostback();"));
if (isInPostback)
Thread.Sleep(200); //sleep for 200ms and query again
}
}


3) Updated the test scenario code as below:


IE ie = new IE("http://localhost/MySite/Default.aspx");
SelectList ddlMaster = ie.SelectList("ddlMaster");
ddlMaster.Option(Find.ByValue("India")).Select();
WaitForAsyncPostBackToComplete(ie);
SelectList ddlChild = ie.SelectList("ddlChild");
ddlChild.Option(Find.ByValue("Hyderabad")).Select();


and all was merry!!!

Hope this is helpful.

pushp