Completed
Push — master ( e2c47b...19fc28 )
by Felipe
52s
created

test/events.js   F

Complexity

Total Complexity 127
Complexity/F 1.02

Size

Lines of Code 706
Function Count 125

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 0
c 1
b 0
f 0
nc 1
dl 0
loc 706
rs 2.1818
wmc 127
mnd 1
bc 125
fnc 125
bpm 1
cpm 1.016
noi 378

How to fix   Complexity   

Complexity

Complex classes like test/events.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
(function() {
2
3
  QUnit.module('Backbone.Events');
4
5
  QUnit.test('on and trigger', function(assert) {
6
    assert.expect(2);
7
    var obj = {counter: 0};
8
    _.extend(obj, Backbone.Events);
9
    obj.on('event', function() { obj.counter += 1; });
10
    obj.trigger('event');
11
    assert.equal(obj.counter, 1, 'counter should be incremented.');
12
    obj.trigger('event');
13
    obj.trigger('event');
14
    obj.trigger('event');
15
    obj.trigger('event');
16
    assert.equal(obj.counter, 5, 'counter should be incremented five times.');
17
  });
18
19
  QUnit.test('binding and triggering multiple events', function(assert) {
20
    assert.expect(4);
21
    var obj = {counter: 0};
22
    _.extend(obj, Backbone.Events);
23
24
    obj.on('a b c', function() { obj.counter += 1; });
25
26
    obj.trigger('a');
27
    assert.equal(obj.counter, 1);
28
29
    obj.trigger('a b');
30
    assert.equal(obj.counter, 3);
31
32
    obj.trigger('c');
33
    assert.equal(obj.counter, 4);
34
35
    obj.off('a c');
36
    obj.trigger('a b c');
37
    assert.equal(obj.counter, 5);
38
  });
39
40
  QUnit.test('binding and triggering with event maps', function(assert) {
41
    var obj = {counter: 0};
42
    _.extend(obj, Backbone.Events);
43
44
    var increment = function() {
45
      this.counter += 1;
46
    };
47
48
    obj.on({
49
      a: increment,
50
      b: increment,
51
      c: increment
52
    }, obj);
53
54
    obj.trigger('a');
55
    assert.equal(obj.counter, 1);
56
57
    obj.trigger('a b');
58
    assert.equal(obj.counter, 3);
59
60
    obj.trigger('c');
61
    assert.equal(obj.counter, 4);
62
63
    obj.off({
64
      a: increment,
65
      c: increment
66
    }, obj);
67
    obj.trigger('a b c');
68
    assert.equal(obj.counter, 5);
69
  });
70
71
  QUnit.test('binding and triggering multiple event names with event maps', function(assert) {
72
    var obj = {counter: 0};
73
    _.extend(obj, Backbone.Events);
74
75
    var increment = function() {
76
      this.counter += 1;
77
    };
78
79
    obj.on({
80
      'a b c': increment
81
    });
82
83
    obj.trigger('a');
84
    assert.equal(obj.counter, 1);
85
86
    obj.trigger('a b');
87
    assert.equal(obj.counter, 3);
88
89
    obj.trigger('c');
90
    assert.equal(obj.counter, 4);
91
92
    obj.off({
93
      'a c': increment
94
    });
95
    obj.trigger('a b c');
96
    assert.equal(obj.counter, 5);
97
  });
98
99
  QUnit.test('binding and trigger with event maps context', function(assert) {
100
    assert.expect(2);
101
    var obj = {counter: 0};
102
    var context = {};
103
    _.extend(obj, Backbone.Events);
104
105
    obj.on({
106
      a: function() {
107
        assert.strictEqual(this, context, 'defaults `context` to `callback` param');
108
      }
109
    }, context).trigger('a');
110
111
    obj.off().on({
112
      a: function() {
113
        assert.strictEqual(this, context, 'will not override explicit `context` param');
114
      }
115
    }, this, context).trigger('a');
116
  });
117
118
  QUnit.test('listenTo and stopListening', function(assert) {
119
    assert.expect(1);
120
    var a = _.extend({}, Backbone.Events);
121
    var b = _.extend({}, Backbone.Events);
122
    a.listenTo(b, 'all', function(){ assert.ok(true); });
123
    b.trigger('anything');
124
    a.listenTo(b, 'all', function(){ assert.ok(false); });
125
    a.stopListening();
126
    b.trigger('anything');
127
  });
128
129
  QUnit.test('listenTo and stopListening with event maps', function(assert) {
130
    assert.expect(4);
131
    var a = _.extend({}, Backbone.Events);
132
    var b = _.extend({}, Backbone.Events);
133
    var cb = function(){ assert.ok(true); };
134
    a.listenTo(b, {event: cb});
135
    b.trigger('event');
136
    a.listenTo(b, {event2: cb});
137
    b.on('event2', cb);
138
    a.stopListening(b, {event2: cb});
139
    b.trigger('event event2');
140
    a.stopListening();
141
    b.trigger('event event2');
142
  });
143
144
  QUnit.test('stopListening with omitted args', function(assert) {
145
    assert.expect(2);
146
    var a = _.extend({}, Backbone.Events);
147
    var b = _.extend({}, Backbone.Events);
148
    var cb = function() { assert.ok(true); };
149
    a.listenTo(b, 'event', cb);
150
    b.on('event', cb);
151
    a.listenTo(b, 'event2', cb);
152
    a.stopListening(null, {event: cb});
153
    b.trigger('event event2');
154
    b.off();
155
    a.listenTo(b, 'event event2', cb);
156
    a.stopListening(null, 'event');
157
    a.stopListening();
158
    b.trigger('event2');
159
  });
160
161
  QUnit.test('listenToOnce', function(assert) {
162
    assert.expect(2);
163
    // Same as the previous test, but we use once rather than having to explicitly unbind
164
    var obj = {counterA: 0, counterB: 0};
165
    _.extend(obj, Backbone.Events);
166
    var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
167
    var incrB = function(){ obj.counterB += 1; };
168
    obj.listenToOnce(obj, 'event', incrA);
169
    obj.listenToOnce(obj, 'event', incrB);
170
    obj.trigger('event');
171
    assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
172
    assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.');
173
  });
174
175
  QUnit.test('listenToOnce and stopListening', function(assert) {
176
    assert.expect(1);
177
    var a = _.extend({}, Backbone.Events);
178
    var b = _.extend({}, Backbone.Events);
179
    a.listenToOnce(b, 'all', function() { assert.ok(true); });
180
    b.trigger('anything');
181
    b.trigger('anything');
182
    a.listenToOnce(b, 'all', function() { assert.ok(false); });
183
    a.stopListening();
184
    b.trigger('anything');
185
  });
186
187
  QUnit.test('listenTo, listenToOnce and stopListening', function(assert) {
188
    assert.expect(1);
189
    var a = _.extend({}, Backbone.Events);
190
    var b = _.extend({}, Backbone.Events);
191
    a.listenToOnce(b, 'all', function() { assert.ok(true); });
192
    b.trigger('anything');
193
    b.trigger('anything');
194
    a.listenTo(b, 'all', function() { assert.ok(false); });
195
    a.stopListening();
196
    b.trigger('anything');
197
  });
198
199
  QUnit.test('listenTo and stopListening with event maps', function(assert) {
200
    assert.expect(1);
201
    var a = _.extend({}, Backbone.Events);
202
    var b = _.extend({}, Backbone.Events);
203
    a.listenTo(b, {change: function(){ assert.ok(true); }});
204
    b.trigger('change');
205
    a.listenTo(b, {change: function(){ assert.ok(false); }});
206
    a.stopListening();
207
    b.trigger('change');
208
  });
209
210
  QUnit.test('listenTo yourself', function(assert) {
211
    assert.expect(1);
212
    var e = _.extend({}, Backbone.Events);
213
    e.listenTo(e, 'foo', function(){ assert.ok(true); });
214
    e.trigger('foo');
215
  });
216
217
  QUnit.test('listenTo yourself cleans yourself up with stopListening', function(assert) {
218
    assert.expect(1);
219
    var e = _.extend({}, Backbone.Events);
220
    e.listenTo(e, 'foo', function(){ assert.ok(true); });
221
    e.trigger('foo');
222
    e.stopListening();
223
    e.trigger('foo');
224
  });
225
226
  QUnit.test('stopListening cleans up references', function(assert) {
227
    assert.expect(12);
228
    var a = _.extend({}, Backbone.Events);
229
    var b = _.extend({}, Backbone.Events);
230
    var fn = function() {};
231
    b.on('event', fn);
232
    a.listenTo(b, 'event', fn).stopListening();
233
    assert.equal(_.size(a._listeningTo), 0);
234
    assert.equal(_.size(b._events.event), 1);
235
    assert.equal(_.size(b._listeners), 0);
236
    a.listenTo(b, 'event', fn).stopListening(b);
237
    assert.equal(_.size(a._listeningTo), 0);
238
    assert.equal(_.size(b._events.event), 1);
239
    assert.equal(_.size(b._listeners), 0);
240
    a.listenTo(b, 'event', fn).stopListening(b, 'event');
241
    assert.equal(_.size(a._listeningTo), 0);
242
    assert.equal(_.size(b._events.event), 1);
243
    assert.equal(_.size(b._listeners), 0);
244
    a.listenTo(b, 'event', fn).stopListening(b, 'event', fn);
245
    assert.equal(_.size(a._listeningTo), 0);
246
    assert.equal(_.size(b._events.event), 1);
247
    assert.equal(_.size(b._listeners), 0);
248
  });
249
250
  QUnit.test('stopListening cleans up references from listenToOnce', function(assert) {
251
    assert.expect(12);
252
    var a = _.extend({}, Backbone.Events);
253
    var b = _.extend({}, Backbone.Events);
254
    var fn = function() {};
255
    b.on('event', fn);
256
    a.listenToOnce(b, 'event', fn).stopListening();
257
    assert.equal(_.size(a._listeningTo), 0);
258
    assert.equal(_.size(b._events.event), 1);
259
    assert.equal(_.size(b._listeners), 0);
260
    a.listenToOnce(b, 'event', fn).stopListening(b);
261
    assert.equal(_.size(a._listeningTo), 0);
262
    assert.equal(_.size(b._events.event), 1);
263
    assert.equal(_.size(b._listeners), 0);
264
    a.listenToOnce(b, 'event', fn).stopListening(b, 'event');
265
    assert.equal(_.size(a._listeningTo), 0);
266
    assert.equal(_.size(b._events.event), 1);
267
    assert.equal(_.size(b._listeners), 0);
268
    a.listenToOnce(b, 'event', fn).stopListening(b, 'event', fn);
269
    assert.equal(_.size(a._listeningTo), 0);
270
    assert.equal(_.size(b._events.event), 1);
271
    assert.equal(_.size(b._listeners), 0);
272
  });
273
274
  QUnit.test('listenTo and off cleaning up references', function(assert) {
275
    assert.expect(8);
276
    var a = _.extend({}, Backbone.Events);
277
    var b = _.extend({}, Backbone.Events);
278
    var fn = function() {};
279
    a.listenTo(b, 'event', fn);
280
    b.off();
281
    assert.equal(_.size(a._listeningTo), 0);
282
    assert.equal(_.size(b._listeners), 0);
283
    a.listenTo(b, 'event', fn);
284
    b.off('event');
285
    assert.equal(_.size(a._listeningTo), 0);
286
    assert.equal(_.size(b._listeners), 0);
287
    a.listenTo(b, 'event', fn);
288
    b.off(null, fn);
289
    assert.equal(_.size(a._listeningTo), 0);
290
    assert.equal(_.size(b._listeners), 0);
291
    a.listenTo(b, 'event', fn);
292
    b.off(null, null, a);
293
    assert.equal(_.size(a._listeningTo), 0);
294
    assert.equal(_.size(b._listeners), 0);
295
  });
296
297
  QUnit.test('listenTo and stopListening cleaning up references', function(assert) {
298
    assert.expect(2);
299
    var a = _.extend({}, Backbone.Events);
300
    var b = _.extend({}, Backbone.Events);
301
    a.listenTo(b, 'all', function(){ assert.ok(true); });
302
    b.trigger('anything');
303
    a.listenTo(b, 'other', function(){ assert.ok(false); });
304
    a.stopListening(b, 'other');
305
    a.stopListening(b, 'all');
306
    assert.equal(_.size(a._listeningTo), 0);
307
  });
308
309
  QUnit.test('listenToOnce without context cleans up references after the event has fired', function(assert) {
310
    assert.expect(2);
311
    var a = _.extend({}, Backbone.Events);
312
    var b = _.extend({}, Backbone.Events);
313
    a.listenToOnce(b, 'all', function(){ assert.ok(true); });
314
    b.trigger('anything');
315
    assert.equal(_.size(a._listeningTo), 0);
316
  });
317
318
  QUnit.test('listenToOnce with event maps cleans up references', function(assert) {
319
    assert.expect(2);
320
    var a = _.extend({}, Backbone.Events);
321
    var b = _.extend({}, Backbone.Events);
322
    a.listenToOnce(b, {
323
      one: function() { assert.ok(true); },
324
      two: function() { assert.ok(false); }
325
    });
326
    b.trigger('one');
327
    assert.equal(_.size(a._listeningTo), 1);
328
  });
329
330
  QUnit.test('listenToOnce with event maps binds the correct `this`', function(assert) {
331
    assert.expect(1);
332
    var a = _.extend({}, Backbone.Events);
333
    var b = _.extend({}, Backbone.Events);
334
    a.listenToOnce(b, {
335
      one: function() { assert.ok(this === a); },
336
      two: function() { assert.ok(false); }
337
    });
338
    b.trigger('one');
339
  });
340
341
  QUnit.test("listenTo with empty callback doesn't throw an error", function(assert) {
342
    assert.expect(1);
343
    var e = _.extend({}, Backbone.Events);
344
    e.listenTo(e, 'foo', null);
345
    e.trigger('foo');
346
    assert.ok(true);
347
  });
348
349
  QUnit.test('trigger all for each event', function(assert) {
350
    assert.expect(3);
351
    var a, b, obj = {counter: 0};
352
    _.extend(obj, Backbone.Events);
353
    obj.on('all', function(event) {
354
      obj.counter++;
355
      if (event === 'a') a = true;
356
      if (event === 'b') b = true;
357
    })
358
    .trigger('a b');
359
    assert.ok(a);
360
    assert.ok(b);
361
    assert.equal(obj.counter, 2);
362
  });
363
364
  QUnit.test('on, then unbind all functions', function(assert) {
365
    assert.expect(1);
366
    var obj = {counter: 0};
367
    _.extend(obj, Backbone.Events);
368
    var callback = function() { obj.counter += 1; };
369
    obj.on('event', callback);
370
    obj.trigger('event');
371
    obj.off('event');
372
    obj.trigger('event');
373
    assert.equal(obj.counter, 1, 'counter should have only been incremented once.');
374
  });
375
376
  QUnit.test('bind two callbacks, unbind only one', function(assert) {
377
    assert.expect(2);
378
    var obj = {counterA: 0, counterB: 0};
379
    _.extend(obj, Backbone.Events);
380
    var callback = function() { obj.counterA += 1; };
381
    obj.on('event', callback);
382
    obj.on('event', function() { obj.counterB += 1; });
383
    obj.trigger('event');
384
    obj.off('event', callback);
385
    obj.trigger('event');
386
    assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
387
    assert.equal(obj.counterB, 2, 'counterB should have been incremented twice.');
388
  });
389
390
  QUnit.test('unbind a callback in the midst of it firing', function(assert) {
391
    assert.expect(1);
392
    var obj = {counter: 0};
393
    _.extend(obj, Backbone.Events);
394
    var callback = function() {
395
      obj.counter += 1;
396
      obj.off('event', callback);
397
    };
398
    obj.on('event', callback);
399
    obj.trigger('event');
400
    obj.trigger('event');
401
    obj.trigger('event');
402
    assert.equal(obj.counter, 1, 'the callback should have been unbound.');
403
  });
404
405
  QUnit.test('two binds that unbind themeselves', function(assert) {
406
    assert.expect(2);
407
    var obj = {counterA: 0, counterB: 0};
408
    _.extend(obj, Backbone.Events);
409
    var incrA = function(){ obj.counterA += 1; obj.off('event', incrA); };
410
    var incrB = function(){ obj.counterB += 1; obj.off('event', incrB); };
411
    obj.on('event', incrA);
412
    obj.on('event', incrB);
413
    obj.trigger('event');
414
    obj.trigger('event');
415
    obj.trigger('event');
416
    assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
417
    assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.');
418
  });
419
420
  QUnit.test('bind a callback with a default context when none supplied', function(assert) {
421
    assert.expect(1);
422
    var obj = _.extend({
423
      assertTrue: function() {
424
        assert.equal(this, obj, '`this` was bound to the callback');
425
      }
426
    }, Backbone.Events);
427
428
    obj.once('event', obj.assertTrue);
429
    obj.trigger('event');
430
  });
431
432
  QUnit.test('bind a callback with a supplied context', function(assert) {
433
    assert.expect(1);
434
    var TestClass = function() {
435
      return this;
436
    };
437
    TestClass.prototype.assertTrue = function() {
438
      assert.ok(true, '`this` was bound to the callback');
439
    };
440
441
    var obj = _.extend({}, Backbone.Events);
442
    obj.on('event', function() { this.assertTrue(); }, new TestClass);
443
    obj.trigger('event');
444
  });
445
446
  QUnit.test('nested trigger with unbind', function(assert) {
447
    assert.expect(1);
448
    var obj = {counter: 0};
449
    _.extend(obj, Backbone.Events);
450
    var incr1 = function(){ obj.counter += 1; obj.off('event', incr1); obj.trigger('event'); };
451
    var incr2 = function(){ obj.counter += 1; };
452
    obj.on('event', incr1);
453
    obj.on('event', incr2);
454
    obj.trigger('event');
455
    assert.equal(obj.counter, 3, 'counter should have been incremented three times');
456
  });
457
458
  QUnit.test('callback list is not altered during trigger', function(assert) {
459
    assert.expect(2);
460
    var counter = 0, obj = _.extend({}, Backbone.Events);
461
    var incr = function(){ counter++; };
462
    var incrOn = function(){ obj.on('event all', incr); };
463
    var incrOff = function(){ obj.off('event all', incr); };
464
465
    obj.on('event all', incrOn).trigger('event');
466
    assert.equal(counter, 0, 'on does not alter callback list');
467
468
    obj.off().on('event', incrOff).on('event all', incr).trigger('event');
469
    assert.equal(counter, 2, 'off does not alter callback list');
470
  });
471
472
  QUnit.test("#1282 - 'all' callback list is retrieved after each event.", function(assert) {
473
    assert.expect(1);
474
    var counter = 0;
475
    var obj = _.extend({}, Backbone.Events);
476
    var incr = function(){ counter++; };
477
    obj.on('x', function() {
478
      obj.on('y', incr).on('all', incr);
479
    })
480
    .trigger('x y');
481
    assert.strictEqual(counter, 2);
482
  });
483
484
  QUnit.test('if no callback is provided, `on` is a noop', function(assert) {
485
    assert.expect(0);
486
    _.extend({}, Backbone.Events).on('test').trigger('test');
487
  });
488
489
  QUnit.test('if callback is truthy but not a function, `on` should throw an error just like jQuery', function(assert) {
490
    assert.expect(1);
491
    var view = _.extend({}, Backbone.Events).on('test', 'noop');
492
    assert.raises(function() {
493
      view.trigger('test');
494
    });
495
  });
496
497
  QUnit.test('remove all events for a specific context', function(assert) {
498
    assert.expect(4);
499
    var obj = _.extend({}, Backbone.Events);
500
    obj.on('x y all', function() { assert.ok(true); });
501
    obj.on('x y all', function() { assert.ok(false); }, obj);
502
    obj.off(null, null, obj);
503
    obj.trigger('x y');
504
  });
505
506
  QUnit.test('remove all events for a specific callback', function(assert) {
507
    assert.expect(4);
508
    var obj = _.extend({}, Backbone.Events);
509
    var success = function() { assert.ok(true); };
510
    var fail = function() { assert.ok(false); };
511
    obj.on('x y all', success);
512
    obj.on('x y all', fail);
513
    obj.off(null, fail);
514
    obj.trigger('x y');
515
  });
516
517
  QUnit.test('#1310 - off does not skip consecutive events', function(assert) {
518
    assert.expect(0);
519
    var obj = _.extend({}, Backbone.Events);
520
    obj.on('event', function() { assert.ok(false); }, obj);
521
    obj.on('event', function() { assert.ok(false); }, obj);
522
    obj.off(null, null, obj);
523
    obj.trigger('event');
524
  });
525
526
  QUnit.test('once', function(assert) {
527
    assert.expect(2);
528
    // Same as the previous test, but we use once rather than having to explicitly unbind
529
    var obj = {counterA: 0, counterB: 0};
530
    _.extend(obj, Backbone.Events);
531
    var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
532
    var incrB = function(){ obj.counterB += 1; };
533
    obj.once('event', incrA);
534
    obj.once('event', incrB);
535
    obj.trigger('event');
536
    assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
537
    assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.');
538
  });
539
540
  QUnit.test('once variant one', function(assert) {
541
    assert.expect(3);
542
    var f = function(){ assert.ok(true); };
543
544
    var a = _.extend({}, Backbone.Events).once('event', f);
545
    var b = _.extend({}, Backbone.Events).on('event', f);
546
547
    a.trigger('event');
548
549
    b.trigger('event');
550
    b.trigger('event');
551
  });
552
553
  QUnit.test('once variant two', function(assert) {
554
    assert.expect(3);
555
    var f = function(){ assert.ok(true); };
556
    var obj = _.extend({}, Backbone.Events);
557
558
    obj
559
      .once('event', f)
560
      .on('event', f)
561
      .trigger('event')
562
      .trigger('event');
563
  });
564
565
  QUnit.test('once with off', function(assert) {
566
    assert.expect(0);
567
    var f = function(){ assert.ok(true); };
568
    var obj = _.extend({}, Backbone.Events);
569
570
    obj.once('event', f);
571
    obj.off('event', f);
572
    obj.trigger('event');
573
  });
574
575
  QUnit.test('once with event maps', function(assert) {
576
    var obj = {counter: 0};
577
    _.extend(obj, Backbone.Events);
578
579
    var increment = function() {
580
      this.counter += 1;
581
    };
582
583
    obj.once({
584
      a: increment,
585
      b: increment,
586
      c: increment
587
    }, obj);
588
589
    obj.trigger('a');
590
    assert.equal(obj.counter, 1);
591
592
    obj.trigger('a b');
593
    assert.equal(obj.counter, 2);
594
595
    obj.trigger('c');
596
    assert.equal(obj.counter, 3);
597
598
    obj.trigger('a b c');
599
    assert.equal(obj.counter, 3);
600
  });
601
602
  QUnit.test('bind a callback with a supplied context using once with object notation', function(assert) {
603
    assert.expect(1);
604
    var obj = {counter: 0};
605
    var context = {};
606
    _.extend(obj, Backbone.Events);
607
608
    obj.once({
609
      a: function() {
610
        assert.strictEqual(this, context, 'defaults `context` to `callback` param');
611
      }
612
    }, context).trigger('a');
613
  });
614
615
  QUnit.test('once with off only by context', function(assert) {
616
    assert.expect(0);
617
    var context = {};
618
    var obj = _.extend({}, Backbone.Events);
619
    obj.once('event', function(){ assert.ok(false); }, context);
620
    obj.off(null, null, context);
621
    obj.trigger('event');
622
  });
623
624
  QUnit.test('Backbone object inherits Events', function(assert) {
625
    assert.ok(Backbone.on === Backbone.Events.on);
626
  });
627
628
  QUnit.test('once with asynchronous events', function(assert) {
629
    var done = assert.async();
630
    assert.expect(1);
631
    var func = _.debounce(function() { assert.ok(true); done(); }, 50);
632
    var obj = _.extend({}, Backbone.Events).once('async', func);
633
634
    obj.trigger('async');
635
    obj.trigger('async');
636
  });
637
638
  QUnit.test('once with multiple events.', function(assert) {
639
    assert.expect(2);
640
    var obj = _.extend({}, Backbone.Events);
641
    obj.once('x y', function() { assert.ok(true); });
642
    obj.trigger('x y');
643
  });
644
645
  QUnit.test('Off during iteration with once.', function(assert) {
646
    assert.expect(2);
647
    var obj = _.extend({}, Backbone.Events);
648
    var f = function(){ this.off('event', f); };
649
    obj.on('event', f);
650
    obj.once('event', function(){});
651
    obj.on('event', function(){ assert.ok(true); });
652
653
    obj.trigger('event');
654
    obj.trigger('event');
655
  });
656
657
  QUnit.test('`once` on `all` should work as expected', function(assert) {
658
    assert.expect(1);
659
    Backbone.once('all', function() {
660
      assert.ok(true);
661
      Backbone.trigger('all');
662
    });
663
    Backbone.trigger('all');
664
  });
665
666
  QUnit.test('once without a callback is a noop', function(assert) {
667
    assert.expect(0);
668
    _.extend({}, Backbone.Events).once('event').trigger('event');
669
  });
670
671
  QUnit.test('listenToOnce without a callback is a noop', function(assert) {
672
    assert.expect(0);
673
    var obj = _.extend({}, Backbone.Events);
674
    obj.listenToOnce(obj, 'event').trigger('event');
675
  });
676
677
  QUnit.test('event functions are chainable', function(assert) {
678
    var obj = _.extend({}, Backbone.Events);
679
    var obj2 = _.extend({}, Backbone.Events);
680
    var fn = function() {};
681
    assert.equal(obj, obj.trigger('noeventssetyet'));
682
    assert.equal(obj, obj.off('noeventssetyet'));
683
    assert.equal(obj, obj.stopListening('noeventssetyet'));
684
    assert.equal(obj, obj.on('a', fn));
685
    assert.equal(obj, obj.once('c', fn));
686
    assert.equal(obj, obj.trigger('a'));
687
    assert.equal(obj, obj.listenTo(obj2, 'a', fn));
688
    assert.equal(obj, obj.listenToOnce(obj2, 'b', fn));
689
    assert.equal(obj, obj.off('a c'));
690
    assert.equal(obj, obj.stopListening(obj2, 'a'));
691
    assert.equal(obj, obj.stopListening());
692
  });
693
694
  QUnit.test('#3448 - listenToOnce with space-separated events', function(assert) {
695
    assert.expect(2);
696
    var one = _.extend({}, Backbone.Events);
697
    var two = _.extend({}, Backbone.Events);
698
    var count = 1;
699
    one.listenToOnce(two, 'x y', function(n) { assert.ok(n === count++); });
700
    two.trigger('x', 1);
701
    two.trigger('x', 1);
702
    two.trigger('y', 2);
703
    two.trigger('y', 2);
704
  });
705
706
})();
707