Tag Archives: internet explorer

Internet Explorer automation/Watin: catching navigation error codes

One question have troubled me for some time when automating Internet Explorer (actually, I am doing web testing with Watin): how to test for HTTP status codes. Finally, I figured out how to do this. The lies in an event that the InternetExplorer object raises when navigation is unsuccessful.

I ended up with writing a C# helper class:

using System.Net;
using WatiN.Core;
using SHDocVw;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Globalization;
namespace Test
{
    public class NavigationObserver
    {
        private HttpStatusCode _statusCode;
        public NavigationObserver(IE ie)
        {
            InternetExplorer internetExplorer = (InternetExplorer)ie.InternetExplorer;
            internetExplorer.NavigateError += new DWebBrowserEvents2_NavigateErrorEventHandler(IeNavigateError);
        }
        public void ShouldHave(HttpStatusCode expectedStatusCode)
        {
            if (!_statusCode.Equals(expectedStatusCode))
            {
                Assert.Fail(string.Format(CultureInfo.InvariantCulture, "Wrong status code. Expected {0}, but was {1}",
                    expectedStatusCode, _statusCode));
            }
        }
        private void IeNavigateError(object pDisp, ref object URL, ref object Frame, ref object StatusCode, ref bool Cancel)
        {
            _statusCode = (HttpStatusCode)StatusCode;
        }
    }
}

Note that I use Visual Studio test runner to run my web tests. Then, I can use this in my test:

using (IE ie = new IE())
{
    NavigationObserver observer = new NavigationObserver(ie);
    ie.GoTo("http://some.where.com");
    observer.ShouldHave(HttpStatusCode.NotFound);
}

Sending POST requests with Watin

When doing web testing using Watin, it is not trivial to be able to do a POST request to the server. However, with the help this article on microsoft.com, I was able to figure out how. I ended up with writing this class:

public class Navigator
{
    private IE _ie;

    public Navigator(IE ie) { _ie = ie; }

    public void Post(Uri baseUri, params KeyValuePair<string, object>[] postData)
    {
        object flags = null;
        object targetFrame = null;
        object headers = "Content-Type: application/x-www-form-urlencoded" + Convert.ToChar(10) + Convert.ToChar(13);
        object postDataBytes = MakeByteStreamOf(postData);
        object resourceLocator = baseUri.ToString();
        IWebBrowser2 browser = (IWebBrowser2)_ie.InternetExplorer;
        browser.Navigate2(ref resourceLocator, ref flags, ref targetFrame, ref postDataBytes, ref headers);
        _ie.WaitForComplete();
    }

    private static byte[] MakeByteStreamOf(KeyValuePair<string, object>[] postData)
    {
        StringBuilder sb = new StringBuilder();
        if (postData.Length > 0)
        {
            foreach (KeyValuePair<string, object> postDataEntry in postData)
            {
                sb.Append(postDataEntry.Key).Append('=').Append(postDataEntry.Value).Append('&');
            }
            sb.Remove(sb.Length - 1, 1);
        }
        return ASCIIEncoding.ASCII.GetBytes(sb.ToString());
    }
}

For example, I can use it like so:

using (IE ie = new IE())
{
    Navigator navigator = new Navigator(ie);
    navigator.Post(new Uri("http://www.foo.com/"), new KeyValuePair<string, object>("p", 1));
    Assert.AreEqual("OK", ie.Text);
}