Sunday, April 08, 2007

Q: How do you make Watin catch a JavaScript confirmation dialog?

A: Use the JavaScript setTimeOut() function

[Parent Advisory: This is GEEK!]

I like Watin for automated unit testing... a lot in many ways. I wish that the documentation was better. More examples would be nice. So here is my modest attempt to contribute to making the world a better place for those of us who have seen the light and understand that Test Driven Development is really the way to go.

Recently I had a problem getting Watin to click JavasScript Confirmation dialog boxes.

Here is what I learned.

Watin testing works in machine time not human time.

Thus, page interaction instructions fire in under a millisecond.

This is OK for web page interactions such as hyperlink and button clicks. But, for Alert and Confirmation dialogs, which live outside of the page, catching a button and firing a click is a problem.

The Confirmation or Alert display takes place too fast for Watin to pick up.

I get "confirmation catching" to happen by putting in a 1 millisecond time delay in the JavaScript in HiThere.htm. This 1 millisecond delay is unnoticeable to human beings but of significance for testing computers.

So here is the HiThere.htm page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Confirmation Thrower</title>
</head>

<script type="text/javascript">

function doWrite()
{
var isGood=confirm('Do you to do this??');
elm = document.getElementById('WriteHere');
if (isGood == true)
{
elm.value = 'I am good';
}
else
{
elm.value = 'I am bad';
}
}


function getConfirmValue()
{
setTimeout('doWrite()', 1);
}

</script>

<body>
<form id="form1">
<a id="YouOK" href="javascript:getConfirmValue()">OK?</a>
<input id="WriteHere" value="" />
</form>
</body>
</html>


Here is the Watin test:

[Test]
public void SimpleConfirmCatchTest()
{
IE ie = new IE();
ie.DialogWatcher.Add(new LogonDialogHandler(WATIN_USER, WATIN_PWD));
ie.GoTo(GetHiTherePage());
ie.ShowWindow(NativeMethods.WindowShowStyle.Maximize);
Link link = ie.Link("YouOK");

link.Click();

ConfirmDialogHandler confirm = new ConfirmDialogHandler();
using (new UseDialogOnce(ie.DialogWatcher, confirm))
{
confirm.WaitUntilExists();
confirm.OKButton.Click();
ie.WaitForComplete();
}
ie.Close();
}

Go here to get the code for UseDialogOnce. (Thanks Trev!)