Using Sinon.JS Fake Timers with CasperJS

One incredibly useful feature of Sinon.JS is its fake timers API. Sinon essentially replaces the global setTimeout and setInterval (as well as clearTimeout and clearInterval) functions with its own functionality. This enables you to have more control over timers and facilitates testing of each timer’s callback function. But there’s something you should be aware of when using this API with CasperJS (or with any testing framework).

A Gotcha with Fake Timers

Using Sinon.JS fake timers with CasperJS is not terribly difficult, so long as you keep the following thing in mind:

The call to sinon.useFakeTimers must occur before any timers are actually set in your code.

This may seem obvious, but it’s something that can easily trip you up if you’re not careful. In order for Sinon to be able to “intercept” those timer-related calls, it needs to start listening for them before your code starts setting them. Making a call to sinon.useFakeTimers after you’ve already called setTimeout or setInterval is already too late, and you won’t be able to control or test their callback functions.

The Code

So what does the code look like?

casper.test.begin("Testing", {
  test: function(test) {
    casper.start();

    casper.thenOpen("http://foo.bar", function() {
      test.assertTitle("Title", "Test page has loaded");

      casper.evaluate(function() {
        // Fake the timer methods.
        window.clock = sinon.useFakeTimers();
      });
    });

    casper.then(function() {
      // Advance the clock 30 seconds.
      casper.evaluate(function() {
        window.clock.tick(30000);
      });

      casper.waitFor(function() {
        // Wait for some condition to change.
      },
      function then() {
        casper.evaluate(function() {
         // Restore the faked methods.
          window.clock.restore();
        });

        // Do some tests.
      });
    });

    casper.run(function() {
      test.done();
    });
  }
});

Note that after the page has opened, we’re attaching the Sinon clock object to the window object in the call to sinon.useFakeTimers. This is so that we can easily refer to it again later when inside of a separate evaluate function.

Next, the clock is advanced 30 seconds (window.clock.tick(30000)) and any timer callbacks that were set to expire within that 30 seconds will execute. After that, it’s just a matter of waiting for some condition to change (as per the functionality in the callback function), and adding some assertions. We also restore the faked timer methods by calling window.clock.restore.

Notice that the useFakeTimers and restore methods aren’t being called in the setup and teardown methods. That’s because the Sinon script is included in my test page, so I need to wait for the page to open and for the Sinon library to have loaded before calling any of its methods.

Do you use SinonJS? What are some of your favorite methods?