Sinon fakeTimers not firing

360 views Asked by At

I'm having an issue with sinon's fakeTimers. This is used in an environment with Marionette.js, underscore and chai test runner. If I set a breakpoint in chrome and walk through, my timer is fired. However, if I don't set a breakpoint then it's never fired.

I'm using _.debounce which is causing a timer to be set.

Here is how the timers are set:

describe('Basket item view', function() {
  beforeEach(function() {
    this.clock = sinon.useFakeTimers();

    this.app = new Backbone.Marionette.Application();
    this.app.addInitializer(basketInit);
    this.app.start(basketOptions);

    this.basketListView = this.app.baskets.currentView;
    this.basketViews = this.basketListView.children;
  });

  afterEach(function() {
    this.app = this.basketListView = null;
    this.clock.restore();
  });

  it('updates amount on quantity change', function() {
    var basketLayoutView = this.basketViews.last();
    var itemView = basketLayoutView.basket.currentView.children.first();
    var items = basketLayoutView.collection;
    var item = items.findWhere({id: 136});

    var $quantity = itemView.$('input.quantity');

    var updatedQuantity = 2;
    var updatedPrice = '20.00';

    $quantity.val(updatedQuantity);
    $quantity.change();

    this.clock.tick(500);

    var newItemView = basketLayoutView.basket.currentView.children.first();
    var $amount = newItemView.$('td.amount.total');
    assert.equal(
        item.get('quantity'), updatedQuantity,
        'quantity change');

    assert.equal(
        $amount.text().trim(), updatedPrice,
        'amount change');
  });
1

There are 1 answers

0
Joe Simpson On BEST ANSWER

The problem was with Underscore.js and it's _.debounce function. It's trying to be more accurate with comparing dates, which is great, breaks testing with sinon.

To fix this I simply overriden the debounce function with the previous version:

_.debounce = function(func, wait, immediate) {
  var timeout, result;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) result = func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) result = func.apply(context, args);
    return result;
  };
};