5 QUnit.module('Backbone.View', {
7 beforeEach: function() {
8 $('#qunit-fixture').append(
9 '<div id="testElement"><h1>Test</h1></div>'
12 view = new Backbone.View({
14 className: 'test-view',
15 other: 'non-special-option'
19 afterEach: function() {
20 $('#testElement').remove();
21 $('#test-view').remove();
26 QUnit.test('constructor', function(assert) {
28 assert.equal(view.el.id, 'test-view');
29 assert.equal(view.el.className, 'test-view');
30 assert.equal(view.el.other, void 0);
33 QUnit.test('$', function(assert) {
35 var myView = new Backbone.View;
36 myView.setElement('<p><a><b>test</b></a></p>');
37 var result = myView.$('a b');
39 assert.strictEqual(result[0].innerHTML, 'test');
40 assert.ok(result.length === +result.length);
43 QUnit.test('$el', function(assert) {
45 var myView = new Backbone.View;
46 myView.setElement('<p><a><b>test</b></a></p>');
47 assert.strictEqual(myView.el.nodeType, 1);
49 assert.ok(myView.$el instanceof Backbone.$);
50 assert.strictEqual(myView.$el[0], myView.el);
53 QUnit.test('initialize', function(assert) {
55 var View = Backbone.View.extend({
56 initialize: function() {
61 assert.strictEqual(new View().one, 1);
64 QUnit.test('preinitialize', function(assert) {
66 var View = Backbone.View.extend({
67 preinitialize: function() {
72 assert.strictEqual(new View().one, 1);
75 QUnit.test('preinitialize occurs before the view is set up', function(assert) {
77 var View = Backbone.View.extend({
78 preinitialize: function() {
79 assert.equal(this.el, undefined);
82 var _view = new View({});
83 assert.notEqual(_view.el, undefined);
86 QUnit.test('render', function(assert) {
88 var myView = new Backbone.View;
89 assert.equal(myView.render(), myView, '#render returns the view instance');
92 QUnit.test('delegateEvents', function(assert) {
94 var counter1 = 0, counter2 = 0;
96 var myView = new Backbone.View({el: '#testElement'});
97 myView.increment = function() { counter1++; };
98 myView.$el.on('click', function() { counter2++; });
100 var events = {'click h1': 'increment'};
102 myView.delegateEvents(events);
103 myView.$('h1').trigger('click');
104 assert.equal(counter1, 1);
105 assert.equal(counter2, 1);
107 myView.$('h1').trigger('click');
108 assert.equal(counter1, 2);
109 assert.equal(counter2, 2);
111 myView.delegateEvents(events);
112 myView.$('h1').trigger('click');
113 assert.equal(counter1, 3);
114 assert.equal(counter2, 3);
117 QUnit.test('delegate', function(assert) {
119 var myView = new Backbone.View({el: '#testElement'});
120 myView.delegate('click', 'h1', function() {
123 myView.delegate('click', function() {
126 myView.$('h1').trigger('click');
128 assert.equal(myView.delegate(), myView, '#delegate returns the view instance');
131 QUnit.test('delegateEvents allows functions for callbacks', function(assert) {
133 var myView = new Backbone.View({el: '<p></p>'});
142 myView.delegateEvents(events);
143 myView.$el.trigger('click');
144 assert.equal(myView.counter, 1);
146 myView.$el.trigger('click');
147 assert.equal(myView.counter, 2);
149 myView.delegateEvents(events);
150 myView.$el.trigger('click');
151 assert.equal(myView.counter, 3);
154 QUnit.test('delegateEvents ignore undefined methods', function(assert) {
156 var myView = new Backbone.View({el: '<p></p>'});
157 myView.delegateEvents({click: 'undefinedMethod'});
158 myView.$el.trigger('click');
161 QUnit.test('undelegateEvents', function(assert) {
163 var counter1 = 0, counter2 = 0;
165 var myView = new Backbone.View({el: '#testElement'});
166 myView.increment = function() { counter1++; };
167 myView.$el.on('click', function() { counter2++; });
169 var events = {'click h1': 'increment'};
171 myView.delegateEvents(events);
172 myView.$('h1').trigger('click');
173 assert.equal(counter1, 1);
174 assert.equal(counter2, 1);
176 myView.undelegateEvents();
177 myView.$('h1').trigger('click');
178 assert.equal(counter1, 1);
179 assert.equal(counter2, 2);
181 myView.delegateEvents(events);
182 myView.$('h1').trigger('click');
183 assert.equal(counter1, 2);
184 assert.equal(counter2, 3);
186 assert.equal(myView.undelegateEvents(), myView, '#undelegateEvents returns the view instance');
189 QUnit.test('undelegate', function(assert) {
191 var myView = new Backbone.View({el: '#testElement'});
192 myView.delegate('click', function() { assert.ok(false); });
193 myView.delegate('click', 'h1', function() { assert.ok(false); });
195 myView.undelegate('click');
197 myView.$('h1').trigger('click');
198 myView.$el.trigger('click');
200 assert.equal(myView.undelegate(), myView, '#undelegate returns the view instance');
203 QUnit.test('undelegate with passed handler', function(assert) {
205 var myView = new Backbone.View({el: '#testElement'});
206 var listener = function() { assert.ok(false); };
207 myView.delegate('click', listener);
208 myView.delegate('click', function() { assert.ok(true); });
209 myView.undelegate('click', listener);
210 myView.$el.trigger('click');
213 QUnit.test('undelegate with selector', function(assert) {
215 var myView = new Backbone.View({el: '#testElement'});
216 myView.delegate('click', function() { assert.ok(true); });
217 myView.delegate('click', 'h1', function() { assert.ok(false); });
218 myView.undelegate('click', 'h1');
219 myView.$('h1').trigger('click');
220 myView.$el.trigger('click');
223 QUnit.test('undelegate with handler and selector', function(assert) {
225 var myView = new Backbone.View({el: '#testElement'});
226 myView.delegate('click', function() { assert.ok(true); });
227 var handler = function() { assert.ok(false); };
228 myView.delegate('click', 'h1', handler);
229 myView.undelegate('click', 'h1', handler);
230 myView.$('h1').trigger('click');
231 myView.$el.trigger('click');
234 QUnit.test('tagName can be provided as a string', function(assert) {
236 var View = Backbone.View.extend({
240 assert.equal(new View().el.tagName, 'SPAN');
243 QUnit.test('tagName can be provided as a function', function(assert) {
245 var View = Backbone.View.extend({
246 tagName: function() {
251 assert.ok(new View().$el.is('p'));
254 QUnit.test('_ensureElement with DOM node el', function(assert) {
256 var View = Backbone.View.extend({
260 assert.equal(new View().el, document.body);
263 QUnit.test('_ensureElement with string el', function(assert) {
265 var View = Backbone.View.extend({
268 assert.strictEqual(new View().el, document.body);
270 View = Backbone.View.extend({
271 el: '#testElement > h1'
273 assert.strictEqual(new View().el, $('#testElement > h1').get(0));
275 View = Backbone.View.extend({
278 assert.ok(!new View().el);
281 QUnit.test('with className and id functions', function(assert) {
283 var View = Backbone.View.extend({
284 className: function() {
292 assert.strictEqual(new View().el.className, 'className');
293 assert.strictEqual(new View().el.id, 'id');
296 QUnit.test('with attributes', function(assert) {
298 var View = Backbone.View.extend({
305 assert.strictEqual(new View().el.className, 'class');
306 assert.strictEqual(new View().el.id, 'id');
309 QUnit.test('with attributes as a function', function(assert) {
311 var View = Backbone.View.extend({
312 attributes: function() {
313 return {'class': 'dynamic'};
317 assert.strictEqual(new View().el.className, 'dynamic');
320 QUnit.test('should default to className/id properties', function(assert) {
322 var View = Backbone.View.extend({
323 className: 'backboneClass',
326 'class': 'attributeClass',
331 var myView = new View;
332 assert.strictEqual(myView.el.className, 'backboneClass');
333 assert.strictEqual(myView.el.id, 'backboneId');
334 assert.strictEqual(myView.$el.attr('class'), 'backboneClass');
335 assert.strictEqual(myView.$el.attr('id'), 'backboneId');
338 QUnit.test('multiple views per element', function(assert) {
341 var $el = $('<p></p>');
343 var View = Backbone.View.extend({
352 var view1 = new View;
353 $el.trigger('click');
354 assert.equal(1, count);
356 var view2 = new View;
357 $el.trigger('click');
358 assert.equal(3, count);
360 view1.delegateEvents();
361 $el.trigger('click');
362 assert.equal(5, count);
365 QUnit.test('custom events', function(assert) {
367 var View = Backbone.View.extend({
370 fake$event: function() { assert.ok(true); }
374 var myView = new View;
375 $('body').trigger('fake$event').trigger('fake$event');
377 $('body').off('fake$event');
378 $('body').trigger('fake$event');
381 QUnit.test('#1048 - setElement uses provided object.', function(assert) {
385 var myView = new Backbone.View({el: $el});
386 assert.ok(myView.$el === $el);
388 myView.setElement($el = $($el));
389 assert.ok(myView.$el === $el);
392 QUnit.test('#986 - Undelegate before changing element.', function(assert) {
394 var button1 = $('<button></button>');
395 var button2 = $('<button></button>');
397 var View = Backbone.View.extend({
400 assert.ok(myView.el === e.target);
405 var myView = new View({el: button1});
406 myView.setElement(button2);
408 button1.trigger('click');
409 button2.trigger('click');
412 QUnit.test('#1172 - Clone attributes object', function(assert) {
414 var View = Backbone.View.extend({
415 attributes: {foo: 'bar'}
418 var view1 = new View({id: 'foo'});
419 assert.strictEqual(view1.el.id, 'foo');
421 var view2 = new View();
422 assert.ok(!view2.el.id);
425 QUnit.test('views stopListening', function(assert) {
427 var View = Backbone.View.extend({
428 initialize: function() {
429 this.listenTo(this.model, 'all x', function() { assert.ok(false); });
430 this.listenTo(this.collection, 'all x', function() { assert.ok(false); });
434 var myView = new View({
435 model: new Backbone.Model,
436 collection: new Backbone.Collection
439 myView.stopListening();
440 myView.model.trigger('x');
441 myView.collection.trigger('x');
444 QUnit.test('Provide function for el.', function(assert) {
446 var View = Backbone.View.extend({
448 return '<p><a></a></p>';
452 var myView = new View;
453 assert.ok(myView.$el.is('p'));
454 assert.ok(myView.$el.has('a'));
457 QUnit.test('events passed in options', function(assert) {
461 var View = Backbone.View.extend({
463 increment: function() {
468 var myView = new View({
470 'click h1': 'increment'
474 myView.$('h1').trigger('click').trigger('click');
475 assert.equal(counter, 2);
478 QUnit.test('remove', function(assert) {
480 var myView = new Backbone.View;
481 document.body.appendChild(view.el);
483 myView.delegate('click', function() { assert.ok(false); });
484 myView.listenTo(myView, 'all x', function() { assert.ok(false); });
486 assert.equal(myView.remove(), myView, '#remove returns the view instance');
487 myView.$el.trigger('click');
490 // In IE8 and below, parentNode still exists but is not document.body.
491 assert.notEqual(myView.el.parentNode, document.body);
494 QUnit.test('setElement', function(assert) {
496 var myView = new Backbone.View({
498 click: function() { assert.ok(false); }
502 click: function() { assert.ok(true); }
504 var oldEl = myView.el;
505 var $oldEl = myView.$el;
507 myView.setElement(document.createElement('div'));
512 assert.notEqual(oldEl, myView.el);
513 assert.notEqual($oldEl, myView.$el);