Julian Jelfs’ Blog

WatiN Dialog Handler for unhandled javascript exceptions

Posted in Unit Testing, WatiN by julianjelfs on September 27, 2011

I’m not sure what WatiN does with javascript exception alerts by default, but I was finding that it seemed to silently close any exception dialog and the test would carry on and would possibly still pass. In my case, I would like the test to fail if there is a javscript error and I would like it to report the text of the javascript error as the reason for the test failure.

First I tried to do this using the NativeMethods supplied with WatiN but I wasn’t able to get at the text description of the error which was important for reporting the reason for test failure. So I then resorted to the UI Automation API found in C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\UIAutomationClient.dll and came up with the following code:

using System.Windows.Automation;
using WatiN.Core.DialogHandlers;
using WatiN.Core.Native.Windows;

namespace WatiNExtensions
{
    public class ScriptExceptionDialogHandler : BaseDialogHandler
    {
        private readonly ITestFailureLogger _logger;

        readonly AndCondition _documentCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                                                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));

        readonly AndCondition _buttonConditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                                                   new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));


        public ScriptExceptionDialogHandler(ITestFailureLogger logger)
        {
            _logger = logger;
        }

        public override bool HandleDialog(Window window)
        {
            if (CanHandleDialog(window))
            {
                var win = AutomationElement.FromHandle(window.Hwnd);
                var documents = win.FindAll(TreeScope.Children, _documentCondition);
                var buttons = win.FindAll(TreeScope.Children, _buttonConditions);

                foreach (AutomationElement document in documents)
                {
                    var textPattern = document.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
                    var text = textPattern.DocumentRange.GetText(-1);
                    _logger.Log(string.Format("Unhandled javascript exception: {0}", text));
                }

                foreach (AutomationElement button in buttons)
                {
                    if(button.Current.AutomationId == "7")
                    {
                        var invokePattern = button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
                        invokePattern.Invoke();
                        break;
                    }
                }
                return true;
            }
            return false;
        }

        public override bool CanHandleDialog(Window window)
        {
            return window.StyleInHex == "94C808CC";
        }
    }
}

This accepts an ITestFailureLogger interface in the constructor, finds the text of the error and logs it, then clicks on the “No” button to dismiss the dialog. What the ITestFailureLogger does is up to you. In my case it just tracks the errors and then checks them in the NUnit test’s tear down. You cannot throw an exception in the dialog handler to stop the test in its tracks because any exception thrown by IDialogHandler.HandleDialog will be swallowed by the WatiN DialogWatcher (understandable but a little bit irritating).

Hope this is of some use to someone.

Advertisements
Tagged with: ,