ログインフォームとして機能するMarionette.jsビューがあります。次のコード サンプルは、既に修正済みのエラーを含む関連するコード部分を示しています。
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");
}
});
});
実装の大きな間違いに気付きました。Revealのコールバック関数closed
で、直接ItemViewを閉じることにしましたが、これはMarionette.js のドキュメントで読むことができるように間違っています。
View は、領域マネージャーによって自動的に呼び出される close メソッドを実装します。
バグ修正:代わりにregionclose()
で呼び出す必要があります。このエラーを修正しました。
ここで、問題をカバーするテストを実際にどのように作成できるかを自問します。テストにはジャスミンを使用します。ItemViewを誤って閉じてフォームを再送信しようとした後、イベント ハンドラーonSignInFormSubmit
が呼び出されなくなったことに気付きました。
これは、残念ながらバグ修正でも失敗するテストの最初のドラフトです。
it("should call the submit handler for the sign-in form", function() {
spyOn(userController.loginView, "onSignInFormSubmit");
spyOn(userController.loginView.signInForm, "validate").andCallFake(function(params) {
return null;
});
userController.loginView.hideForm();
userController.loginView.ui.signInForm.trigger("submit");
expect(userController.loginView.onSignInFormSubmit).toHaveBeenCalled();
});
次のようにイベントハンドラーが登録されているかどうかをテストすることもできます。
expect(userController.loginView.events["submit #signin-form"]).toEqual("onSignInFormSubmit");