commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-old / civicrm / packages / backbone-forms / test / form.js
1 ;(function(Form, Field, editors) {
2
3
4 module("Form", {
5 setup: function() {
6 this.sinon = sinon.sandbox.create();
7 },
8
9 teardown: function() {
10 this.sinon.restore();
11 }
12 });
13
14 test("'schema' option - Schema object is used to create the form", function() {
15 var post = new Post(),
16 customSchema = { name: {} };
17
18 var form = new Form({
19 model: post,
20 schema: customSchema,
21 idPrefix: null
22 }).render();
23
24 //Check correct fields have been added
25 equal($('input', form.el).length, 1);
26 equal($('input:eq(0)', form.el).attr('id'), 'name');
27 });
28
29 test("'schema' option - If not present, the 'schema' attribute on the model is used", function() {
30 var post = new Post();
31
32 var form = new Form({
33 model: post
34 }).render();
35
36 //Stored correct schema object
37 equal(form.schema, post.schema);
38
39 //Check correct fields have been added
40 equal($('input', form.el).length, 3);
41 equal($('textarea', form.el).length, 1);
42 });
43
44 test('The schema on the model can be a function', function() {
45 var post = new Post,
46 _schema = post.schema;
47
48 post.schema = function() {
49 return _schema;
50 }
51
52 var form = new Form({
53 model: post
54 }).render();
55
56
57
58 //Stored correct schema object
59 equal(form.schema, _schema);
60 });
61
62 test("'model' option - Populates the form", function() {
63 var post = new Post();
64
65 var form = new Form({
66 model: post,
67 idPrefix: null
68 }).render();
69
70 equal($('#title', form.el).val(), 'Danger Zone!');
71 equal($('#author', form.el).val(), 'Sterling Archer');
72 });
73
74 test("'data' option - Used if no model provided. Populates the form.", function() {
75 var data = {
76 title: 'Yuuup',
77 author: 'Lana Kang'
78 };
79
80 var form = new Form({
81 data: data,
82 schema: {
83 title: {},
84 author: {}
85 }
86 }).render();
87
88 equal($('#title', form.el).val(), 'Yuuup');
89 equal($('#author', form.el).val(), 'Lana Kang');
90 });
91
92 test("'fields' option - Allows choosing and ordering fields from the schema", function() {
93 var form = new Form({
94 model: new Post,
95 fields: ['author', 'slug'],
96 idPrefix: null
97 }).render();
98
99 equal($('input:eq(0)', form.el).attr('id'), 'author');
100 equal($('input:eq(1)', form.el).attr('id'), 'slug');
101 });
102
103 test("'fieldsets' option - Allows choosing and ordering of fields within fieldsets", function () {
104 var form = new Form({
105 model: new Post,
106 fieldsets: [
107 ['slug', 'author'],
108 {'legend': 'Content Section', 'fields': ['title', 'content']}
109 ],
110 idPrefix: null
111 }).render();
112
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');
119 });
120
121 test("'idPrefix' option - Adds prefix to all DOM element IDs", function() {
122 var form = new Form({
123 model: new Post,
124 idPrefix: 'form_'
125 }).render();
126
127 equal($('#form_title', form.el).length, 1);
128 });
129
130 test("'template' option - Specifies template", function() {
131 Form.templates.customForm = Form.helpers.createTemplate('<div class="custom-form"><form>{{fieldsets}}</form></div>');
132
133 var form = new Form({
134 model: new Post,
135 template: 'customForm'
136 }).render();
137
138 ok(form.$el.hasClass('custom-form'));
139 })
140
141
142 test("validate() - validates the form and returns an errors object", function () {
143 var form = new Form({
144 schema: {
145 title: {validators: ['required']}
146 }
147 }).render();
148
149 var err = form.validate();
150
151 equal(err.title.type, 'required');
152 equal(err.title.message, 'Required');
153
154 form.setValue({title: 'A valid title'});
155 equal(form.validate(), null);
156 });
157
158 test('validate() - returns model validation errors', function() {
159 var post = new Post;
160
161 post.validate = function() {
162 return 'FOO';
163 };
164
165 var form = new Form({
166 model: post,
167 schema: {
168 title: {validators: ['required']}
169 }
170 }).render();
171
172 var err = form.validate();
173
174 deepEqual(err, {
175 _others: ['FOO']
176 });
177 });
178
179 test('commit() - returns validation errors', function() {
180 var form = new Form({
181 model: new Post
182 }).render();
183
184 //Mock
185 form.validate = function() {
186 return { foo: 'bar' }
187 };
188
189 var err = form.commit();
190
191 equal(err.foo, 'bar');
192 });
193
194 test('commit() - returns model validation errors', function() {
195 var post = new Post;
196
197 post.validate = function() {
198 return 'ERROR';
199 };
200
201 var form = new Form({
202 model: post
203 }).render();
204
205 var err = form.commit();
206
207 deepEqual(err, {
208 _others: ['ERROR']
209 });
210 });
211
212 test("commit() - updates the model with form values", function() {
213 var post = new Post();
214
215 var form = new Form({
216 model: post,
217 idPrefix: null
218 }).render();
219
220 //Change the title in the form and save
221 $('#title', form.el).val('New title');
222 form.commit();
223
224 equal(post.get('title'), 'New title');
225 });
226
227 test('commit() - triggers model change once', function() {
228 var post = new Post;
229
230 var form = new Form({
231 model: post
232 }).render();
233
234 //Count change events
235 var timesCalled = 0;
236 post.on('change', function() {
237 timesCalled ++;
238 });
239
240 form.fields.title.setValue('New title');
241 form.fields.author.setValue('New author');
242 form.commit();
243
244 equal(timesCalled, 1);
245 });
246
247 test("getValue() - returns form value as an object", function() {
248 var data = {
249 title: 'Yuuup',
250 author: 'Lana Kang'
251 };
252
253 var form = new Form({
254 data: data,
255 schema: {
256 title: {},
257 author: {}
258 }
259 }).render();
260
261 //Change the title in the form and save
262 $('#title', form.el).val('Nooope');
263
264 var result = form.getValue();
265
266 equal(result.title, 'Nooope');
267 equal(result.author, 'Lana Kang');
268 });
269
270 test("getValue(key) - returns specific field value", function() {
271 var form = new Form({
272 model: new Post
273 }).render();
274
275 equal(form.getValue('title'), 'Danger Zone!');
276 });
277
278 test("setValue() - updates form field values", function() {
279 var form = new Form({
280 model: new Post
281 }).render();
282
283 form.setValue({
284 title: 'Danger Zone 2',
285 slug: 'danger-zone-2'
286 });
287
288 //Check changed fields
289 equal(form.fields.title.getValue(), 'Danger Zone 2');
290 equal(form.fields.slug.getValue(), 'danger-zone-2');
291
292 //Check fields that shouldn't have changed
293 equal(form.fields.author.getValue(), 'Sterling Archer');
294
295 //Check callig with key, val as arguments
296 form.setValue('title', 'Danger Zone 3');
297
298 //Check changed fields
299 equal(form.fields.title.getValue(), 'Danger Zone 3');
300 });
301
302 test("setValue() - ignore attributes not in form", function() {
303 var form = new Form({
304 model: new Post
305 }).render();
306
307 form.setValue({
308 title: 'Danger Zone 3',
309 notInForm: 'Not in my form you don\'t'
310 });
311
312 //Check changed fields
313 equal(form.fields.title.getValue(), 'Danger Zone 3');
314
315 //Check fields that shouldn't have changed
316 equal(form.fields.author.getValue(), 'Sterling Archer');
317 });
318
319 test("focus() - gives focus to form and its first editor", function() {
320 var form = new Form({
321 model: new Post
322 }).render();
323
324 form.focus();
325
326 stop();
327 setTimeout(function() {
328 ok(form.fields.title.editor.hasFocus);
329 ok(form.hasFocus);
330
331 start();
332 }, 0);
333 });
334
335 test("focus() - triggers the 'focus' event", function() {
336 var form = new Form({
337 model: new Post
338 }).render();
339
340 var spy = this.sinon.spy();
341
342 form.on('focus', spy);
343
344 form.focus();
345
346 stop();
347 setTimeout(function() {
348 ok(spy.called);
349 ok(spy.calledWith(form));
350
351 start();
352 }, 0);
353 });
354
355 test("blur() - removes focus from the form and its first editor", function() {
356 var form = new Form({
357 model: new Post
358 }).render();
359
360 form.focus();
361
362 form.blur();
363
364 stop();
365 setTimeout(function() {
366 ok(!form.fields.title.editor.hasFocus);
367 ok(!form.hasFocus);
368
369 start();
370 }, 0);
371 });
372
373 test("blur() - triggers the 'blur' event", function() {
374 var form = new Form({
375 model: new Post
376 }).render();
377
378 form.focus();
379
380 var spy = this.sinon.spy();
381
382 form.on('blur', spy);
383
384 form.blur();
385
386 stop();
387 setTimeout(function() {
388 ok(spy.called);
389 ok(spy.calledWith(form));
390
391 start();
392 }, 0);
393 });
394
395 test("setValue() - updates only field from schema", function() {
396 var form = new Form({
397 model: new Post
398 }).render();
399
400 form.setValue({
401 title: 'Danger Zone 2',
402 fakeField: 'FakeTest'
403 });
404
405 // Check undefined schema field
406 equal(typeof form.fields.fakeField, 'undefined');
407 });
408
409 test("remove() - removes all child views and itself", function() {
410 var counter = 0;
411
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() {
415 counter++;
416 }
417
418 var form = new Form({
419 model: new Post,
420 fields: ['author', 'title', 'content', 'slug']
421 }).render();
422
423 form.remove();
424
425 //remove() should have been called twice for each field (editor and field)
426 //and once for the form itself
427 equal(counter, 9);
428
429 //Restore remove method
430 Backbone.View.prototype.remove = _remove;
431 });
432
433 test("'change' event - bubbles up from editor", function() {
434 var form = new Form({
435 model: new Post
436 }).render();
437
438 var spy = this.sinon.spy();
439
440 form.on('change', spy);
441
442 form.fields.title.editor.trigger('change', form.fields.title.editor);
443
444 ok(spy.called);
445 ok(spy.calledWith(form));
446 });
447
448 test("'focus' event - bubbles up from editor when form doesn't have focus", function() {
449 var form = new Form({
450 model: new Post
451 }).render();
452
453 var spy = this.sinon.spy();
454
455 form.on('focus', spy);
456
457 form.fields.title.editor.focus();
458
459 ok(spy.called);
460 ok(spy.calledWith(form));
461 });
462
463 test("'focus' event - doesn't bubble up from editor when form already has focus", function() {
464 var form = new Form({
465 model: new Post
466 }).render();
467
468 form.focus();
469
470 var spy = this.sinon.spy();
471
472 form.on('focus', spy);
473
474 form.fields.title.editor.focus();
475
476 ok(!spy.called);
477 });
478
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({
481 model: new Post
482 }).render();
483
484 form.focus();
485
486 var spy = this.sinon.spy();
487
488 form.on('blur', spy);
489
490 form.fields.title.editor.blur();
491
492 stop();
493 setTimeout(function() {
494 ok(spy.called);
495 ok(spy.calledWith(form));
496
497 start();
498 }, 0);
499 });
500
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({
503 model: new Post
504 }).render();
505
506 form.focus();
507
508 var spy = this.sinon.spy();
509
510 form.on('blur', spy);
511
512 form.fields.title.editor.blur();
513 form.fields.author.editor.focus();
514
515 stop();
516 setTimeout(function() {
517 ok(!spy.called);
518
519 start();
520 }, 0);
521 });
522
523 test("'blur' event - doesn't bubble up from editor when form doesn't have focus", function() {
524 var form = new Form({
525 model: new Post
526 }).render();
527
528 var spy = this.sinon.spy();
529
530 form.on('blur', spy);
531
532 form.fields.title.editor.blur();
533
534 stop();
535 setTimeout(function() {
536 ok(!spy.called);
537
538 start();
539 }, 0);
540 });
541
542 test("Events bubbling up from editors", function() {
543 var form = new Form({
544 model: new Post
545 }).render();
546
547 var spy = this.sinon.spy();
548
549 form.on('title:whatever', spy);
550
551 form.fields.title.editor.trigger('whatever', form.fields.title.editor);
552
553 ok(spy.called);
554 ok(spy.calledWith(form, form.fields.title.editor));
555 });
556
557 test('Allows access to field views', function() {
558 var form = new Form({
559 model: new Post
560 }).render();
561
562 ok(form.fields.title instanceof Form.Field);
563 ok(form.fields.author instanceof Form.Field);
564 });
565
566 test("Supports picking nested fields from within Objects", function() {
567 var Model = Backbone.Model.extend({
568 schema: {
569 title: {},
570 author: { type: 'Object', subSchema: {
571 id: { type: 'Number' },
572 name: { type: 'Object', subSchema: {
573 first: {},
574 last: {}
575 }}
576 }}
577 }
578 });
579
580 var form = new Form({
581 model: new Model,
582 fields: ['title', 'author.id', 'author.name.last']
583 }).render();
584
585 deepEqual(_.keys(form.fields), ['title', 'author.id', 'author.name.last']);
586
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);
590 });
591
592
593
594 })(Backbone.Form, Backbone.Form.Field, Backbone.Form.editors);