M_rivermount
M_rivermount

Reputation: 511

Jasmine test Backbone view events

I'm trying to test my Backbone.view using grunt, karma, jasmine 2 and chrome as output browser. My view is responding to a click event:

el: $('#wrap'),
events: {
    (...)
    'click #sender'           : 'observeSender',
    (...)
},

Where sender is a div (rendered by the view) in a menu bar, and the observeSender() method brings up a UI window. My test for this:

it('should show error dialog', function() {
    var model = new fooModel({ 'config' : config });
    var view = new barview({ model: model });
    expect($('#errors-dialog').is(':visible')).toBe(false);
    sender = $('#wrap').find('div#sender').eq(0);
    sender.trigger('click');
    expect($('#errors-dialog').is(':visible')).toBe(true);
});

This test fails. I've tried a ton of stuff and finally, if I change my view to this:

events: {
    (...)
    //'click #sender'           : 'observeSender',
    (...)
},
initialize: function(options) {
    (...)
    $('#sender').on('click', function(){ self.observeSender.call(self); });
}

Now the test passes. The first example works fine when trying the app live but it is not testable, second option works once but not after the #sender is re-rendered (due to other events). I would still like to have it organised the first way, so what am I doing wrong?

Update 1

As suggested I switched all my queries in the test to view.$, but the test is still failing on

expect(view.$('#errors-dialog').is(':visible')).toBe(true);

Update 2

I need to clarify that the observeSender() method is responsible for bringing up a UI dialog. It is never called. My question is not about elements in the DOM, it's all there, I use the Karma Debug Runner and Chrome console to check it.

If I replace the entire contents of the observeSender method with a console.log('hello'); statement, I will never see the output of it using the first approach where I define the click event "the backbone way". As I see it, something is going on with the events during the test.

Update 3

I've gone through the tests for the backbone library and copied over a test from their view tests

it('should delegateEvents', function() {
    var counter1 = 0, counter2 = 0;

    var view = new Backbone.View({el: '#testElement'});
    view.increment = function(){ counter1++; };
    view.$el.on('click', function(){ counter2++; });

    var events = {'click h1': 'increment'};

    view.delegateEvents(events);
    view.$('h1').trigger('click');
    expect(counter1).toBe(1);
    expect(counter2).toBe(1);

    view.$('h1').trigger('click');
    expect(counter1).toBe(2);
    expect(counter2).toBe(2);

    view.delegateEvents(events);
    view.$('h1').trigger('click');
    expect(counter1).toBe(3);
    expect(counter2).toBe(3);
});

The output is:

Expected 0 to be 1.
Error: Expected 0 to be 1.
    at /.../Spec.js:20572
Expected 0 to be 1.
Error: Expected 0 to be 1.
    at /.../Spec.js:20573
Expected 0 to be 2.
Error: Expected 0 to be 2.
    at /.../Spec.js:20576
Expected 0 to be 2.
Error: Expected 0 to be 2.
    at /.../Spec.js:20577
Expected 0 to be 3.
Error: Expected 0 to be 3.
    at /../Spec.js:20581
Expected 0 to be 3.
Error: Expected 0 to be 3.

Ran it in both Chrome and PhantomJS, same result, I'm going to go dig into Jasmine now...

Upvotes: 2

Views: 1671

Answers (1)

M_rivermount
M_rivermount

Reputation: 511

I'm now using the jasmine-jquery library. Since I am using browserify to build everything, together with jQuery, it does not work to put the jasmine-jquery library in my karma.conf. Instead it must be included after jQuery, so it goes in the Spec.js:

var jasminejquery = require('jasmine-jquery');

Then add fixtures and trigger the click:

describe('Example', function() {
    beforeEach(function(){
        setFixtures('<body><div id="wrap"></div></body>');
    });
    it('should init application and draw stuff', function() {
        var application = new App({container: 'body'});
        // (...)
        $('#sender').click();
    });
});

and everything is working as expected.

Upvotes: 1

Related Questions