Using WebDriver to automatically check for JavaScript errors on every page

Update: please see my newer post on this that doesn’t require changes to your application.


One of the benefits of using a page-object model is that you can perform certain actions on every page in your application that you visit, such as checking for accessibility.

One such check is automatically checking for JavaScript errors on page load. There’s a couple of approaches out there, one involves copying and pasting a small snippet of JavaScript into each page. Since our application we are working on uses a standard template for every page, we simply add some JavaScript to the common page header that is the first thing to load on the page, and catches any JavaScript errors that occur:

define(["amdUtils/string/interpolate"], function(interpolate) {
    window.jsErrors = [];

    window.onerror = function (errorMessage, url, lineNumber) {
        var message = interpolate("Error: [{{0}}], url: [{{1}}], line: [{{2}}]", [errorMessage, url, lineNumber]);
        window.jsErrors.push(message);
        return false;
    };
});

It’s then a matter of checking the jsErrors each time we visit a page, this is example C# code we use in the base page class for every page.

var js = driver as IJavaScriptExecutor;
ICollection javascriptErrors = null;
for (var i = 0; i < 20; i++)
{
  javascriptErrors = js.ExecuteScript("return window.jsErrors") as ICollection;
  if (javascriptErrors != null) break;
  System.Threading.Thread.Sleep(1000);
}
Assert.IsNotNull(javascriptErrors, "Can't seem to load JavaScript on the page to find JavaScript errors. Check that JavaScript is enabled.");
var javaScriptErrorsAsString = javascriptErrors.Cast<string>().Aggregate("", (current, error) => current + (error + ", "));
Assert.AreEqual("", javaScriptErrorsAsString, "Found JavaScript errors on page load: " + javaScriptErrorsAsString);

This code waits until it can read the jsErrors on the page. If it can’t, it means that JavaScript didn’t load and this is an error. Once it gets the jsErrors, it checks that there are none.

This code has been very useful for us. It has caught a number of JavaScript errors, and is especially great for finding cross browser JavaScript issues, as we run our acceptance tests in 5 different browsers.

Watir-page-helper has been end-of-lifed

Intro

I am happy to announce that the watir-page-helper gem has been end-of-lifed: meaning no further development will happen on it and it will remain as it stands. I am thoroughly supportive of Cheezy’s page-object gem and recommend you move onto this when you have the first opportunity to do so.

Background

When I initially released this gem, Cheezy had yet to release his page-object gem. I borrowed a lot of his concepts and packaged them into a gem specifically for watir-webdriver. A few weeks later, Cheezy released his page-object gem that not only supports watir-webdriver, but also selenium-webdriver. He has iterated faster than I have and his gem has come along way to support additional features such as defining page-routes and default data. I have supplied a couple of tiny pull requests to him and there is nothing now that watir-page-helper can offer that page-object can’t, so I am EOL’ing watir-page-helper.

So how do I change to use page-object instead of watir-page-helper?

I converted an existing suite of tests that use watir-page-helper to run against Etsy to use the page-object gem (link to tests). It was a fairly straightforward task, and here are the fundamental differences:

  • Accessing an actual element object is done via an _element suffix: for example, defining a link :home, provides a home_element method. Watir-page-helper provided a home_link method, and I prefer Cheezy’s approach (the home_link method is actually supported by page-object but you should move away from it).
  • Watir-page-helper supported p,li,ol as methods, but these are defined as paragraph, list_item, and ordered_list in page-object.

Using Cheezy’s Page Factory

One of the neat features of the page-object gem is the page factory. This is a way to conveniently access pages from Cucumber steps and the like.

There are a couple of things you need to do:

In env.rb, you should mix in the PageObject::PageFactory module

require 'page-object/page_factory'
World(PageObject::PageFactory)

You then have access to helper methods to visit and set the page you want to use (originally there were just visit_page, and on_page, but I added on and visit – I think they read nicer):

visit_page RegistrationPage
on_page HomePage
visit HomePage
on HomePage

Summary

Good things come to an end and get replaced by even better things. Here’s to your future success using the page-object gem.