1 ;(function(Form
, Field
, editors
) {
6 this.sinon
= sinon
.sandbox
.create();
14 test("'schema' option - Schema object is used to create the form", function() {
15 var post
= new Post(),
16 customSchema
= { name
: {} };
24 //Check correct fields have been added
25 equal($('input', form
.el
).length
, 1);
26 equal($('input:eq(0)', form
.el
).attr('id'), 'name');
29 test("'schema' option - If not present, the 'schema' attribute on the model is used", function() {
30 var post
= new Post();
36 //Stored correct schema object
37 equal(form
.schema
, post
.schema
);
39 //Check correct fields have been added
40 equal($('input', form
.el
).length
, 3);
41 equal($('textarea', form
.el
).length
, 1);
44 test('The schema on the model can be a function', function() {
46 _schema
= post
.schema
;
48 post
.schema = function() {
58 //Stored correct schema object
59 equal(form
.schema
, _schema
);
62 test("'model' option - Populates the form", function() {
63 var post
= new Post();
70 equal($('#title', form
.el
).val(), 'Danger Zone!');
71 equal($('#author', form
.el
).val(), 'Sterling Archer');
74 test("'data' option - Used if no model provided. Populates the form.", function() {
88 equal($('#title', form
.el
).val(), 'Yuuup');
89 equal($('#author', form
.el
).val(), 'Lana Kang');
92 test("'fields' option - Allows choosing and ordering fields from the schema", function() {
95 fields
: ['author', 'slug'],
99 equal($('input:eq(0)', form
.el
).attr('id'), 'author');
100 equal($('input:eq(1)', form
.el
).attr('id'), 'slug');
103 test("'fieldsets' option - Allows choosing and ordering of fields within fieldsets", function () {
104 var form
= new Form({
108 {'legend': 'Content Section', 'fields': ['title', 'content']}
113 ok(form
.$(':nth-child(1)').is('fieldset'), 'First element of the form is not a fieldset');
114 equal(form
.$('fieldset:nth-child(1) input:eq(0)').attr('id'), 'slug');
115 equal(form
.$('fieldset:nth-child(1) input:eq(1)').attr('id'), 'author');
116 equal(form
.$('fieldset:nth-child(2) legend').html(), 'Content Section');
117 equal(form
.$('fieldset:nth-child(2) input:eq(0)').attr('id'), 'title');
118 equal(form
.$('fieldset:nth-child(2) textarea').attr('id'), 'content');
121 test("'idPrefix' option - Adds prefix to all DOM element IDs", function() {
122 var form
= new Form({
127 equal($('#form_title', form
.el
).length
, 1);
130 test("'template' option - Specifies template", function() {
131 Form
.templates
.customForm
= Form
.helpers
.createTemplate('<div class="custom-form"><form>{{fieldsets}}</form></div>');
133 var form
= new Form({
135 template
: 'customForm'
138 ok(form
.$el
.hasClass('custom-form'));
142 test("validate() - validates the form and returns an errors object", function () {
143 var form
= new Form({
145 title
: {validators
: ['required']}
149 var err
= form
.validate();
151 equal(err
.title
.type
, 'required');
152 equal(err
.title
.message
, 'Required');
154 form
.setValue({title
: 'A valid title'});
155 equal(form
.validate(), null);
158 test('validate() - returns model validation errors', function() {
161 post
.validate = function() {
165 var form
= new Form({
168 title
: {validators
: ['required']}
172 var err
= form
.validate();
179 test('commit() - returns validation errors', function() {
180 var form
= new Form({
185 form
.validate = function() {
186 return { foo
: 'bar' }
189 var err
= form
.commit();
191 equal(err
.foo
, 'bar');
194 test('commit() - returns model validation errors', function() {
197 post
.validate = function() {
201 var form
= new Form({
205 var err
= form
.commit();
212 test("commit() - updates the model with form values", function() {
213 var post
= new Post();
215 var form
= new Form({
220 //Change the title in the form and save
221 $('#title', form
.el
).val('New title');
224 equal(post
.get('title'), 'New title');
227 test('commit() - triggers model change once', function() {
230 var form
= new Form({
234 //Count change events
236 post
.on('change', function() {
240 form
.fields
.title
.setValue('New title');
241 form
.fields
.author
.setValue('New author');
244 equal(timesCalled
, 1);
247 test("getValue() - returns form value as an object", function() {
253 var form
= new Form({
261 //Change the title in the form and save
262 $('#title', form
.el
).val('Nooope');
264 var result
= form
.getValue();
266 equal(result
.title
, 'Nooope');
267 equal(result
.author
, 'Lana Kang');
270 test("getValue(key) - returns specific field value", function() {
271 var form
= new Form({
275 equal(form
.getValue('title'), 'Danger Zone!');
278 test("setValue() - updates form field values", function() {
279 var form
= new Form({
284 title
: 'Danger Zone 2',
285 slug
: 'danger-zone-2'
288 //Check changed fields
289 equal(form
.fields
.title
.getValue(), 'Danger Zone 2');
290 equal(form
.fields
.slug
.getValue(), 'danger-zone-2');
292 //Check fields that shouldn't have changed
293 equal(form
.fields
.author
.getValue(), 'Sterling Archer');
295 //Check callig with key, val as arguments
296 form
.setValue('title', 'Danger Zone 3');
298 //Check changed fields
299 equal(form
.fields
.title
.getValue(), 'Danger Zone 3');
302 test("setValue() - ignore attributes not in form", function() {
303 var form
= new Form({
308 title
: 'Danger Zone 3',
309 notInForm
: 'Not in my form you don\'t'
312 //Check changed fields
313 equal(form
.fields
.title
.getValue(), 'Danger Zone 3');
315 //Check fields that shouldn't have changed
316 equal(form
.fields
.author
.getValue(), 'Sterling Archer');
319 test("focus() - gives focus to form and its first editor", function() {
320 var form
= new Form({
327 setTimeout(function() {
328 ok(form
.fields
.title
.editor
.hasFocus
);
335 test("focus() - triggers the 'focus' event", function() {
336 var form
= new Form({
340 var spy
= this.sinon
.spy();
342 form
.on('focus', spy
);
347 setTimeout(function() {
349 ok(spy
.calledWith(form
));
355 test("blur() - removes focus from the form and its first editor", function() {
356 var form
= new Form({
365 setTimeout(function() {
366 ok(!form
.fields
.title
.editor
.hasFocus
);
373 test("blur() - triggers the 'blur' event", function() {
374 var form
= new Form({
380 var spy
= this.sinon
.spy();
382 form
.on('blur', spy
);
387 setTimeout(function() {
389 ok(spy
.calledWith(form
));
395 test("setValue() - updates only field from schema", function() {
396 var form
= new Form({
401 title
: 'Danger Zone 2',
402 fakeField
: 'FakeTest'
405 // Check undefined schema field
406 equal(typeof form
.fields
.fakeField
, 'undefined');
409 test("remove() - removes all child views and itself", function() {
412 //Mock out the remove method so we can tell how many times it was called
413 var _remove
= Backbone
.View
.prototype.remove
;
414 Backbone
.View
.prototype.remove = function() {
418 var form
= new Form({
420 fields
: ['author', 'title', 'content', 'slug']
425 //remove() should have been called twice for each field (editor and field)
426 //and once for the form itself
429 //Restore remove method
430 Backbone
.View
.prototype.remove
= _remove
;
433 test("'change' event - bubbles up from editor", function() {
434 var form
= new Form({
438 var spy
= this.sinon
.spy();
440 form
.on('change', spy
);
442 form
.fields
.title
.editor
.trigger('change', form
.fields
.title
.editor
);
445 ok(spy
.calledWith(form
));
448 test("'focus' event - bubbles up from editor when form doesn't have focus", function() {
449 var form
= new Form({
453 var spy
= this.sinon
.spy();
455 form
.on('focus', spy
);
457 form
.fields
.title
.editor
.focus();
460 ok(spy
.calledWith(form
));
463 test("'focus' event - doesn't bubble up from editor when form already has focus", function() {
464 var form
= new Form({
470 var spy
= this.sinon
.spy();
472 form
.on('focus', spy
);
474 form
.fields
.title
.editor
.focus();
479 test("'blur' event - bubbles up from editor when form has focus and we're not focusing on another one of the form's editors", function() {
480 var form
= new Form({
486 var spy
= this.sinon
.spy();
488 form
.on('blur', spy
);
490 form
.fields
.title
.editor
.blur();
493 setTimeout(function() {
495 ok(spy
.calledWith(form
));
501 test("'blur' event - doesn't bubble up from editor when form has focus and we're focusing on another one of the form's editors", function() {
502 var form
= new Form({
508 var spy
= this.sinon
.spy();
510 form
.on('blur', spy
);
512 form
.fields
.title
.editor
.blur();
513 form
.fields
.author
.editor
.focus();
516 setTimeout(function() {
523 test("'blur' event - doesn't bubble up from editor when form doesn't have focus", function() {
524 var form
= new Form({
528 var spy
= this.sinon
.spy();
530 form
.on('blur', spy
);
532 form
.fields
.title
.editor
.blur();
535 setTimeout(function() {
542 test("Events bubbling up from editors", function() {
543 var form
= new Form({
547 var spy
= this.sinon
.spy();
549 form
.on('title:whatever', spy
);
551 form
.fields
.title
.editor
.trigger('whatever', form
.fields
.title
.editor
);
554 ok(spy
.calledWith(form
, form
.fields
.title
.editor
));
557 test('Allows access to field views', function() {
558 var form
= new Form({
562 ok(form
.fields
.title
instanceof Form
.Field
);
563 ok(form
.fields
.author
instanceof Form
.Field
);
566 test("Supports picking nested fields from within Objects", function() {
567 var Model
= Backbone
.Model
.extend({
570 author
: { type
: 'Object', subSchema
: {
571 id
: { type
: 'Number' },
572 name
: { type
: 'Object', subSchema
: {
580 var form
= new Form({
582 fields
: ['title', 'author.id', 'author.name.last']
585 deepEqual(_
.keys(form
.fields
), ['title', 'author.id', 'author.name.last']);
587 ok(form
.fields
['title'].editor
instanceof Form
.editors
.Text
);
588 ok(form
.fields
['author.id'].editor
instanceof Form
.editors
.Number
);
589 ok(form
.fields
['author.name.last'].editor
instanceof Form
.editors
.Text
);
594 })(Backbone
.Form
, Backbone
.Form
.Field
, Backbone
.Form
.editors
);