Created
December 18, 2012 19:07
-
-
Save alexbeletsky/4330928 to your computer and use it in GitHub Desktop.
Backbone.View done with TDD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Feedback = Backbone.Model.extend({ | |
url: '/feedback', | |
validate: function (attrs) { | |
var errors = []; | |
if (!attrs.email || attrs.email === '') { | |
errors.push({name: 'email', message: 'Please fill email field.'}); | |
} | |
if (!attrs.feedback || attrs.feedback === '') { | |
errors.push({name: 'feedback', message: 'Please fill feedback field.'}); | |
} | |
return errors.length > 0 ? errors : false; | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var FeedbackFormView = Backbone.View.extend({ | |
className: 'row', | |
template: '\ | |
<form>\ | |
<legend>Share the feedback</legend>\ | |
<div class="control-group email">\ | |
<label>Email</label>\ | |
<input type="text" id="email" placeholder="Your email address...">\ | |
<span class="help-inline"></span>\ | |
</div>\ | |
<div class="control-group website">\ | |
<label>Web site</label>\ | |
<input type="text" id="website" placeholder="Your website...">\ | |
<span class="help-inline"></span>\ | |
</div>\ | |
<div class="control-group feedback">\ | |
<label>Feedback</label>\ | |
<textarea id="feedback" class="input-xxlarge" placeholder="Feedback text..." rows="6"><%= feedback %></textarea>\ | |
<span class="help-inline"></span>\ | |
</div>\ | |
<button type="submit" id="submit" class="btn">Submit</button>\ | |
</form>\ | |
', | |
events: { | |
'click #submit': 'submitClicked' | |
}, | |
initialize: function (options) { | |
if (!this.model) { | |
throw new Error('model is required'); | |
} | |
if (!(options && options.feedback)) { | |
throw new Error('feedback is required'); | |
} | |
this.feedback = options.feedback; | |
}, | |
render: function () { | |
this.$el.html(_.template(this.template, {feedback: this.feedback})); | |
return this; | |
}, | |
submitClicked: function (e) { | |
e.preventDefault(); | |
var me = this; | |
var options = { | |
success: function () { | |
me.hideErrors(); | |
}, | |
error: function (model, errors) { | |
me.showErrors(errors); | |
} | |
}; | |
var feedback = { | |
email: this.$('#email').val(), | |
website: this.$('#website').val(), | |
feedback: this.$('#feedback').val() | |
}; | |
this.model.save(feedback, options); | |
}, | |
showErrors: function(errors) { | |
_.each(errors, function (error) { | |
var controlGroup = this.$('.' + error.name); | |
controlGroup.addClass('error'); | |
controlGroup.find('.help-inline').text(error.message); | |
}, this); | |
}, | |
hideErrors: function () { | |
this.$('.control-group').removeClass('error'); | |
this.$('.help-inline').text(''); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe('FeedbackFormView.js spec', function () { | |
var view, model; | |
beforeEach(function () { | |
view = new FeedbackFormView({model: new Feedback(), feedback: 'TDD is awesome..' }); | |
}); | |
describe('when view is constructing', function () { | |
it ('should exist', function () { | |
expect(view).toBeDefined(); | |
}); | |
}); | |
describe('when view is initialized', function () { | |
describe('without model', function () { | |
it('should throw exception', function () { | |
expect(function () { | |
new FeedbackFormView(); | |
}).toThrow(new Error('model is required')); | |
}); | |
}); | |
describe('without default feedback', function () { | |
it('should throw exception', function () { | |
expect(function () { | |
new FeedbackFormView({model: new Backbone.Model() }); | |
}).toThrow(new Error('feedback is required')); | |
}); | |
}); | |
}); | |
describe('when view is rendered', function () { | |
beforeEach(function () { | |
view.render(); | |
}); | |
it ('should email field be empty', function () { | |
expect(view.$el.find('input#email')).toHaveValue(''); | |
}); | |
it ('should website field be empty', function () { | |
expect(view.$el.find('input#website')).toHaveValue(''); | |
}); | |
it ('should feedback field with default feedback', function () { | |
expect(view.$el.find('textarea#feedback')).toHaveValue('TDD is awesome..'); | |
}); | |
}); | |
describe('when view is changing', function () { | |
beforeEach(function () { | |
view.render(); | |
}); | |
describe('when form is submitted', function () { | |
describe('no inputs are filled', function () { | |
beforeEach(function () { | |
view.$el.find('#email').val('').trigger('change'); | |
view.$el.find('#feedback').val('').trigger('change'); | |
}); | |
beforeEach(function () { | |
view.$el.find('#submit').trigger('click'); | |
}); | |
it('email field should be invalidated', function () { | |
expect(view.$el.find('.control-group.email')).toHaveClass('error'); | |
}); | |
it('feedback field should be invalidated', function () { | |
expect(view.$el.find('.control-group.feedback')).toHaveClass('error'); | |
}); | |
it('website field should be valid', function () { | |
expect(view.$el.find('.control-group.website')).not.toHaveClass('error'); | |
}); | |
}); | |
describe('only email field filled', function () { | |
beforeEach(function () { | |
view.$el.find('#email').val('a@a.com').trigger('change'); | |
view.$el.find('#feedback').val('').trigger('change'); | |
}); | |
beforeEach(function () { | |
view.$el.find('#submit').trigger('click'); | |
}); | |
it('email field should be valid', function () { | |
expect(view.$el.find('.control-group.email')).not.toHaveClass('error'); | |
}); | |
it('feedback field should be invalidated', function () { | |
expect(view.$el.find('.control-group.feedback')).toHaveClass('error'); | |
}); | |
it('website field should be valid', function () { | |
expect(view.$el.find('.control-group.website')).not.toHaveClass('error'); | |
}); | |
}); | |
describe('email and feedback filled', function () { | |
beforeEach(function () { | |
spyOn(view.model, 'save').andCallThrough(); | |
}); | |
beforeEach(function () { | |
view.$el.find('#email').val('a@a.com').trigger('change'); | |
view.$el.find('#feedback').val('some feedback').trigger('change'); | |
}); | |
beforeEach(function () { | |
view.$el.find('#submit').trigger('click'); | |
}); | |
it('should show no errors', function () { | |
expect(view.$el.find('.error').length).toBe(0); | |
}); | |
it('should save model', function () { | |
expect(view.model.save).toHaveBeenCalled(); | |
}); | |
}); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment