Julian Jelfs’ Blog

WatiN Javascript Alert Dialog Handler

Posted in Unit Testing, WatiN by julianjelfs on October 7, 2011

The javascript alert handler that comes with WatiN out of the box didn’t quite do what I wanted. I needed something that could be automatically running the whole time and dismiss the alert whenever it happens but notify my code that the alert had happened and what the alert message had been. So I came up with the following modification to the WatiN version which suits my purpose:

    public class JavaScriptAlertDialogHandler : BaseDialogHandler
    {
        private readonly Action _onAlert;

        public JavaScriptAlertDialogHandler(Action onAlert)
        {
            _onAlert = onAlert;
        }

        public override bool HandleDialog(Window window)
        {
            if (CanHandleDialog(window))
            {
                _onAlert(window.Message);
                new WinButton(GetOKButtonId(), window.Hwnd).Click();
                return true;
            }
            return false;
        }

        public override bool CanHandleDialog(Window window)
        {
            return (window.StyleInHex == "94C801C5" && !ButtonWithId1Exists(window.Hwnd));
        }

        private static int GetOKButtonId()
        {
            return 2;
        }

        protected static bool ButtonWithId1Exists(IntPtr windowHwnd)
        {
            var button = new WinButton(1, windowHwnd);
            return button.Exists();
        }
    }

So when you construct the handler you pass in an Action that will receive the text of the message when the handler handles an alert e.g.

    IE.AddDialogHandler(new JavaScriptAlertDialogHandler(s => ScriptAlert = s));

Hope this is of some use to someone else too …

Tagged with:

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.

Tagged with: ,