Bryce Fischer
Bryce Fischer

Reputation: 5442

Backbone.js and Jasmine Spys Not Getting Called

I'm trying to test that when an element is clicked, that a function is called. Easy enough it would seem, but I must be missing something stupid because I can't seem to get this simple example to work.

Here is my View

(function($) {
    window.LaserMonitor = {
        Views: {}
    };

    window.LaserMonitor.Views.WorkstationSummary = Backbone.View.extend({
        tagName: 'li',
        className: 'StationItem',

        initialize: function() {
            _.bindAll(this, 'showDetails');
            this.template = _.template($("#WorkstationSummary").html());
        },

        events: {
            'click h3' : 'showDetails'
        },

        showDetails: function() {
        },

        render: function() {
            var renderedTmpl = this.template(this.model.toJSON());

            $(this.el).append(renderedTmpl);

            return this;
        }
    });
})(jQuery);

and here is my Jasmine test:

describe('WorkstationSummary Item', function() {
    beforeEach(function() {
        _.templateSettings = {
          interpolate: /\{\{(.+?)\}\}/g,
          evaluate: /\{\{(.+?)\}\}/g
        };      

        loadFixtures('LaserMonitorFixture.html');

        this.model = new Backbone.Model({
            id: 1,
            name: 'D8',
            assigned: 1900,
            inProgress: 4,
            completed: 5
        });

        this.view = new window.LaserMonitor.Views.WorkstationSummary({model: this.model});
    });

    describe('Events', function() {
        beforeEach(function() {
            this.view.render();
        });

        it('should trigger click event', function() {
            this.header = this.view.$('h3');

            spyOn(this.view, 'showDetails');

            this.header.click();

            expect(this.view.showDetails).toHaveBeenCalled();
        });
    });
});

The result of this running is:

Error: Expected spy on showDetails to have been called. at new (http://localhost:57708/JobMgr2/test-js/lib/jasmine-1.0.2/jasmine.js:102:32) at [object Object].toHaveBeenCalled (http://localhost:57708/JobMgr2/test-js/lib/jasmine-1.0.2/jasmine.js:1171:29) at [object Object]. (http://localhost:57708/JobMgr2/test-js/spec/LaserMonitorSpec.js:33:34) at [object Object].execute (http://localhost:57708/JobMgr2/test-js/lib/jasmine-1.0.2/jasmine.js:1001:15) at [object Object].next_ (http://localhost:57708/JobMgr2/test-js/lib/jasmine-1.0.2/jasmine.js:1790:31) at http://localhost:57708/JobMgr2/test-js/lib/jasmine-1.0.2/jasmine.js:1780:18

EDIT: Adding the fixture template for completness:

<script type="text/template" id="WorkstationSummary">
    <h3>{{ name }} ({{ assigned }}/{{ inProgress }}/{{ completed }})</h3>
    <ul>
    </ul>
</script>

Upvotes: 4

Views: 2036

Answers (2)

Abhilash M A
Abhilash M A

Reputation: 564

If you create a spy for method, while running the test, instead of calling the actual method the spy get called. The spy is a wrapper around the method. But here the problem is you have created the view before you created the spy. So the actual method is getting called instead of the spy. What you have to do is create the spy before creating the view object. I have used sinon.js to spy on the methods. And you have to use the prototype of the view to spy on a method of that view:

var workStationSpy = sinon.spy(window.LaserMonitor.Views.WorkstationSummary.prototype, "showDetails");
this.view = new window.LaserMonitor.Views.WorkstationSummary({model: this.model});
this.view.render();
expect(workStationSpy).toHaveBeenCalled();
workStationSpy.restore();

Upvotes: 5

StevenMcD
StevenMcD

Reputation: 17482

I would change it to the following and try:

it('should trigger click event', function() {
    var viewToTest = this.view;
    this.header = viewToTest.$('h3');
    spyOn(viewToTest, 'showDetails');
    this.header.click();
    expect(viewToTest.showDetails).toHaveBeenCalled(); 
});

My worry with calling "this.view" could lead to scoping issues. Its a wild guess that I have not tested but I think its worth a try. Good luck!

Upvotes: 0

Related Questions