↩ Back to base

Stubbing window.location in JavaScript

Wednesday 6 February 2013

Let's imagine you have the following code:

var el = document.getElementById("some-container");
el.addEventListener('click', handleClick, false);

function handleClick(e) {
  var link = e.target.getElementsByTagName('a')[0]
  if(link) {
    if(e.metaKey) {
      return window.open(link.href);
    }
    window.location = link.href;
  }
}

How do I test this?

Short answer: You don't. The reason is that the browser will not allow you to override anything in the window host object.

Long answer: Your best bet is to abstract any 'window' related logic into your own methods. For example, let's create a redirect helper method:

function redirect(path, _blank) {
  if(path) {
    if(_blank) {
      return window.open(path);
    }
    return window.location = path;
  }
}

Now let's utilize this method to simplify the handleClick method.

function handleClick(e) {
  var link = e.target.getElementsByTagName('a')[0]
  if(link) {
    redirect(link.href, e.metaKey);
  }
}

Stub it all

Testing it will now be possible by stubbing out our redirect method. I'm using Sinon.js here, a library that provides excellent tooling for stubs.

sinon.stub(window, 'redirect');

// Create a fixture
var div = document.createElement('div');
div.innerHTML = '<a href="#hello">Hello</a>';

// Override event object
var e = {
  target : div,
  metaKey: false
};

// Call our method
handleClick(e);

// Assert
stub.calledWith('#hello', false); // === true

That's all folks. Happy testing!

/Daniel