Question

Let's say we have a simple Backbone View, like this:

class MyView extends Backbone.View

    events: 
        'click .save': 'onSave'

    onSave: (event) ->
        event.preventDefault()

        # do something interesting

I want to test that event.preventDefault() gets called when I click on my element with the .save class.

I could test the implementation of my callback function, pretty much like this (Mocha + Sinon.js):

it 'prevents default submission', ->
    myView.onSave()

    myView.args[0][0].preventDefault.called.should.be.true

I don't think it's working but this is only to get the idea; writing the proper code, this works. My problem here is that this way I'm testing the implementation and not the functionality.

So, my question really is: how can I verify , supposing to trigger a click event on my .save element?

it 'prevents default submission', ->
    myView.$('.save').click()

    # assertion here ??

Thanks as always :)

Was it helpful?

Solution

Try adding a listener on the view's $el, then triggering click on .save, then verify the event hasn't bubbled up to the view's element.

var view = new MyView();
var called = false;
function callback() { called = true; }

view.render();

// Attach a listener on the view's element
view.$el.on('click', callback);

// Test
view.$('.save').trigger('click');

// Verify
expect(called).toBeFalsy();

OTHER TIPS

So you want to test that preventDefault is called when a click event is generated, correct?

Couldn't you do something like (in JavaScript. I'll leave the CoffeeScript as an exercise ;)):

var preventDefaultSpy;

before(function() {
  preventDefaultSpy = sinon.spy(Event.prototype, 'preventDefault');
});

after(function() {
  preventDefaultSpy.restore();
});

it('should call "preventDefault"', function() {
  myView.$('.save').click();
  expect(preventDefaultSpy.callCount).to.equal(1);
});

You might want to call preventDefaultSpy.reset() just before creating the click event so the call count is not affected by other things going on.

I haven't tested it, but I believe it would work.

edit: in other words, since my answer is not that different from a part of your question: I think your first approach is ok. By spying on Event.prototype you don't call myView so it's acting more as a black box, which might alleviate some of your concerns.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top