Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to test debounced Backbone view event

When I am not throttling/debouncing the function the test passes.

However when I debounce the event to prevent flooding the server the test no longer passes. Mocha outputs AssertionError: expected execute to have been called at least once, but it was never called

It should be noted that the debounced call works without errors in the live code. Which is why I'm thoroughly confused why the test fails.

The Test:

describe('When information is entered into the search fields', function () {
    it('vents up the search:for:churches command', function () {
        var executeStub = sinon.stub(App, 'execute');

        view = new SearchForm()
        view.render();

        view.$el.find('input[name=church_name]').val('baptist')
        view.$el.find('input[name=zip]').val('61615')

        view.$el.find('input[name=zip]').trigger($.Event('keypress'))

        expect(executeStub).to.have.been.called

        view.close();
        PEP.execute.restore()
    });
});

Un-throttled:

var SearchForm = Backbone.Marionette.ItemView.extend({

    template: 'search_form',
    events: {
        'keypress [data-search-field]' : 'searchForChurches'
    },

    searchForChurches: function() {
        console.log('not debounced')
        var searchData = Backbone.Syphon.serialize(this);
        App.execute("search:for:churches", searchData);
    }

});

Throttled:

var SearchForm = Backbone.Marionette.ItemView.extend({

    template: 'search_form',
    events: {
        'keypress [data-search-field]' : 'searchForChurches'
    },

    searchForChurches: _.debounce(function() {
        console.log('debounced')
        var searchData = Backbone.Syphon.serialize(this);
        App.execute("search:for:churches", searchData);
    }, 200)

});

Edit: I have also posted a related follow-up question: https://stackoverflow.com/questions/21167488/how-to-test-a-debounced-throttled-backbone-view-event-with-mocha-to-ensure-its-a

like image 718
JonathanW Avatar asked Dec 09 '22 10:12

JonathanW


2 Answers

There is a problem, when using UnderscoreJS with SinonJS.

  • The debounce function in UnderscoreJS uses _.now.
  • SinonJS covers the Date object, but doesn't cover _.now.

For testing purposes, i replace _.now in the test's bootstrap file:

_.now = function() {
  return new Date().getTime();
};
like image 71
arz.freezy Avatar answered Dec 10 '22 22:12

arz.freezy


Simon's approach worked great for most cases but I kept bumping into different situations that were causing more errors. After spending more time with it and looking at sinon's documentation I think I have a better approach.

Sinon's Fake Timers to the rescue.

describe('When information is entered into the search fields', function () {
    it('vents up the search:for:churches command', function () {
        var clock = sinon.useFakeTimers();
        var executeStub = sinon.stub(App, 'execute');

        view = new SearchForm()
        view.render();

        view.$el.find('input[name=church_name]').val('baptist')
        view.$el.find('input[name=zip]').val('61615')

        view.$el.find('input[name=zip]').trigger($.Event('keypress'))
        clock.tick(200)

        expect(executeStub).to.have.been.called

        view.close();
        PEP.execute.restore()
        clock.restore()    
    });
});
like image 44
JonathanW Avatar answered Dec 10 '22 22:12

JonathanW