How do I test Ember.run.later with Sinon?

ember.js, sinon

Solution

Beware that sinon.useFakeTimers (by default on) overrides the window.Date. That becomes an issue once you already have a scheduled Ember runloop and the useFakeTimers() is turned on. This is because Backburner (the Ember.js runloop implementation) setTimeout /core scheduling method/ tries hard to optimize calling window.setTimeout (look for `executeAt` in ember.js)

After going through the sinon source I made the following mod to let those two get along nicely (gist). It instructs sinon not to touch the window.Date and also patches sinon.test() to wait few more ticks after the test body which allows scheduled timers to get executed and async codes

sinon._originalUseFakeTimers = sinon.useFakeTimers;
sinon.useFakeTimers = function() {
    // make sure we don't override window.Date used in
    // Backburner.setTimeout() to optimize window.setTimeout() call numbers
    return sinon._originalUseFakeTimers.apply(this, [new Date().getTime(), "setTimeout", "setInterval", "clearTimeout", "clearInterval"]);
};

sinon._originalTest = sinon.test;
sinon.test = function(callback) {
    return sinon._originalTest.call(this, function() {
        callback.apply(this, arguments);

        // wait for further runloops to finish (2s is the mocha timeout)
        this.clock.tick(2000);
    });
};

Problem

I have some Ember code that sets a timeout: ``` var MyObject = Ember.Object.extend({ setFooToBarLater: function() { Ember.run.later(this, 'set', 'foo', 'bar', 500); } }); ``` I'd like to test that using Sinon's fake clock. Here's what I tried: ``` var clock = sinon.useFakeTimers(); var myObject = MyObject.create(); myObject.setFooToBarLater(); clock.tick(600); expect(myObject.get('foo')).to.be('bar'); ``` But the `expect` always runs before the `set`. I also tried wrapping the `clock.tick` in a run-loop: ``` Ember.run(clock, 'tick', 600); ```

Original source