Reputation: 5442
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
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
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