Saturday, 17 August 2013

How to test if an event handler is set in a Marionette.js view?

How to test if an event handler is set in a Marionette.js view?

There is a Marionette.js view which acts as a login form. The following
code sample shows the relevant code parts including an error I already
fixed:
MyApp.module("User", function(User, App, Backbone, Marionette, $, _) {
User.LoginView = Marionette.ItemView.extend({
className: "reveal-modal",
template: "user/login",
ui: {
signInForm: "#signin-form"
},
events: {
"submit #signin-form": "onSignInFormSubmit"
},
onRender: function() {
var self = this;
var $el = this.$el;
// [...] Render schema
_.defer(function(){
$el.reveal({
closeOnBackgroundClick: false,
closed: function(){
self.close(); // <-- This is incorrect. Do not close the
ItemView directly!
}
});
});
},
onSignInFormSubmit: function(event) {
event.preventDefault();
var errors = this.signInForm.validate();
var data = this.signInForm.getValue();
// [...] Notify that data has been submitted.
},
hideForm: function() {
this.$el.trigger("reveal:close");
}
});
});
I noticed a major mistake in my implementation. In the callback function
closed of Reveal I decided to close the ItemView directly which is wrong
as you can read in the documentation of Marionette.js:
View implements a close method, which is called by the region managers
automatically.
Bugfix: Instead close() should be called on the region. I fixed this error.



Now I ask myself how can I actually write a test which covers the problem.
I use Jasmine for testing. I noticed that the event handler
onSignInFormSubmit is no longer called after I have incorrectly closed the
ItemView and try to re-submit the form.
Here is a first draft of the test which unfortunately does fail** also
with the bugfix:
it("should call the submit handler for the sign-in form", function() {
var callback = jasmine.createSpy("FormSubmitSpy");
spyOn(userController.loginView.signInForm,
"validate").andCallFake(function(params) {
return null;
});
userController.loginView.bind("onSignInFormSubmit", callback, this);
userController.loginView.hideForm();
userController.loginView.ui.signInForm.trigger("submit");
expect(callback).toHaveBeenCalled();
});

No comments:

Post a Comment