/test/collection.js
JavaScript | 2112 lines | 1877 code | 217 blank | 18 comment | 17 complexity | 52c72f67bf221b2c21a969f7509232f9 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1(function(QUnit) { 2 3 var a, b, c, d, e, col, otherCol; 4 5 QUnit.module('Backbone.Collection', { 6 7 beforeEach: function(assert) { 8 a = new Backbone.Model({id: 3, label: 'a'}); 9 b = new Backbone.Model({id: 2, label: 'b'}); 10 c = new Backbone.Model({id: 1, label: 'c'}); 11 d = new Backbone.Model({id: 0, label: 'd'}); 12 e = null; 13 col = new Backbone.Collection([a, b, c, d]); 14 otherCol = new Backbone.Collection(); 15 } 16 17 }); 18 19 QUnit.test('new and sort', function(assert) { 20 assert.expect(6); 21 var counter = 0; 22 col.on('sort', function(){ counter++; }); 23 assert.deepEqual(col.pluck('label'), ['a', 'b', 'c', 'd']); 24 col.comparator = function(m1, m2) { 25 return m1.id > m2.id ? -1 : 1; 26 }; 27 col.sort(); 28 assert.equal(counter, 1); 29 assert.deepEqual(col.pluck('label'), ['a', 'b', 'c', 'd']); 30 col.comparator = function(model) { return model.id; }; 31 col.sort(); 32 assert.equal(counter, 2); 33 assert.deepEqual(col.pluck('label'), ['d', 'c', 'b', 'a']); 34 assert.equal(col.length, 4); 35 }); 36 37 QUnit.test('String comparator.', function(assert) { 38 assert.expect(1); 39 var collection = new Backbone.Collection([ 40 {id: 3}, 41 {id: 1}, 42 {id: 2} 43 ], {comparator: 'id'}); 44 assert.deepEqual(collection.pluck('id'), [1, 2, 3]); 45 }); 46 47 QUnit.test('new and parse', function(assert) { 48 assert.expect(3); 49 var Collection = Backbone.Collection.extend({ 50 parse: function(data) { 51 return _.filter(data, function(datum) { 52 return datum.a % 2 === 0; 53 }); 54 } 55 }); 56 var models = [{a: 1}, {a: 2}, {a: 3}, {a: 4}]; 57 var collection = new Collection(models, {parse: true}); 58 assert.strictEqual(collection.length, 2); 59 assert.strictEqual(collection.first().get('a'), 2); 60 assert.strictEqual(collection.last().get('a'), 4); 61 }); 62 63 QUnit.test('clone preserves model and comparator', function(assert) { 64 assert.expect(3); 65 var Model = Backbone.Model.extend(); 66 var comparator = function(model){ return model.id; }; 67 68 var collection = new Backbone.Collection([{id: 1}], { 69 model: Model, 70 comparator: comparator 71 }).clone(); 72 collection.add({id: 2}); 73 assert.ok(collection.at(0) instanceof Model); 74 assert.ok(collection.at(1) instanceof Model); 75 assert.strictEqual(collection.comparator, comparator); 76 }); 77 78 QUnit.test('get', function(assert) { 79 assert.expect(6); 80 assert.equal(col.get(0), d); 81 assert.equal(col.get(d.clone()), d); 82 assert.equal(col.get(2), b); 83 assert.equal(col.get({id: 1}), c); 84 assert.equal(col.get(c.clone()), c); 85 assert.equal(col.get(col.first().cid), col.first()); 86 }); 87 88 QUnit.test('get with non-default ids', function(assert) { 89 assert.expect(5); 90 var MongoModel = Backbone.Model.extend({idAttribute: '_id'}); 91 var model = new MongoModel({_id: 100}); 92 var collection = new Backbone.Collection([model], {model: MongoModel}); 93 assert.equal(collection.get(100), model); 94 assert.equal(collection.get(model.cid), model); 95 assert.equal(collection.get(model), model); 96 assert.equal(collection.get(101), void 0); 97 98 var collection2 = new Backbone.Collection(); 99 collection2.model = MongoModel; 100 collection2.add(model.attributes); 101 assert.equal(collection2.get(model.clone()), collection2.first()); 102 }); 103 104 QUnit.test('has', function(assert) { 105 assert.expect(15); 106 assert.ok(col.has(a)); 107 assert.ok(col.has(b)); 108 assert.ok(col.has(c)); 109 assert.ok(col.has(d)); 110 assert.ok(col.has(a.id)); 111 assert.ok(col.has(b.id)); 112 assert.ok(col.has(c.id)); 113 assert.ok(col.has(d.id)); 114 assert.ok(col.has(a.cid)); 115 assert.ok(col.has(b.cid)); 116 assert.ok(col.has(c.cid)); 117 assert.ok(col.has(d.cid)); 118 var outsider = new Backbone.Model({id: 4}); 119 assert.notOk(col.has(outsider)); 120 assert.notOk(col.has(outsider.id)); 121 assert.notOk(col.has(outsider.cid)); 122 }); 123 124 QUnit.test('update index when id changes', function(assert) { 125 assert.expect(4); 126 var collection = new Backbone.Collection(); 127 collection.add([ 128 {id: 0, name: 'one'}, 129 {id: 1, name: 'two'} 130 ]); 131 var one = collection.get(0); 132 assert.equal(one.get('name'), 'one'); 133 collection.on('change:name', function(model) { assert.ok(this.get(model)); }); 134 one.set({name: 'dalmatians', id: 101}); 135 assert.equal(collection.get(0), null); 136 assert.equal(collection.get(101).get('name'), 'dalmatians'); 137 }); 138 139 QUnit.test('at', function(assert) { 140 assert.expect(2); 141 assert.equal(col.at(2), c); 142 assert.equal(col.at(-2), c); 143 }); 144 145 QUnit.test('pluck', function(assert) { 146 assert.expect(1); 147 assert.equal(col.pluck('label').join(' '), 'a b c d'); 148 }); 149 150 QUnit.test('add', function(assert) { 151 assert.expect(14); 152 var added, opts, secondAdded; 153 added = opts = secondAdded = null; 154 e = new Backbone.Model({id: 10, label: 'e'}); 155 otherCol.add(e); 156 otherCol.on('add', function() { 157 secondAdded = true; 158 }); 159 col.on('add', function(model, collection, options){ 160 added = model.get('label'); 161 opts = options; 162 }); 163 col.add(e, {amazing: true}); 164 assert.equal(added, 'e'); 165 assert.equal(col.length, 5); 166 assert.equal(col.last(), e); 167 assert.equal(otherCol.length, 1); 168 assert.equal(secondAdded, null); 169 assert.ok(opts.amazing); 170 171 var f = new Backbone.Model({id: 20, label: 'f'}); 172 var g = new Backbone.Model({id: 21, label: 'g'}); 173 var h = new Backbone.Model({id: 22, label: 'h'}); 174 var atCol = new Backbone.Collection([f, g, h]); 175 assert.equal(atCol.length, 3); 176 atCol.add(e, {at: 1}); 177 assert.equal(atCol.length, 4); 178 assert.equal(atCol.at(1), e); 179 assert.equal(atCol.last(), h); 180 181 var coll = new Backbone.Collection(new Array(2)); 182 var addCount = 0; 183 coll.on('add', function(){ 184 addCount += 1; 185 }); 186 coll.add([undefined, f, g]); 187 assert.equal(coll.length, 5); 188 assert.equal(addCount, 3); 189 coll.add(new Array(4)); 190 assert.equal(coll.length, 9); 191 assert.equal(addCount, 7); 192 }); 193 194 QUnit.test('add multiple models', function(assert) { 195 assert.expect(6); 196 var collection = new Backbone.Collection([{at: 0}, {at: 1}, {at: 9}]); 197 collection.add([{at: 2}, {at: 3}, {at: 4}, {at: 5}, {at: 6}, {at: 7}, {at: 8}], {at: 2}); 198 for (var i = 0; i <= 5; i++) { 199 assert.equal(collection.at(i).get('at'), i); 200 } 201 }); 202 203 QUnit.test('add; at should have preference over comparator', function(assert) { 204 assert.expect(1); 205 var Col = Backbone.Collection.extend({ 206 comparator: function(m1, m2) { 207 return m1.id > m2.id ? -1 : 1; 208 } 209 }); 210 211 var collection = new Col([{id: 2}, {id: 3}]); 212 collection.add(new Backbone.Model({id: 1}), {at: 1}); 213 214 assert.equal(collection.pluck('id').join(' '), '3 1 2'); 215 }); 216 217 QUnit.test('add; at should add to the end if the index is out of bounds', function(assert) { 218 assert.expect(1); 219 var collection = new Backbone.Collection([{id: 2}, {id: 3}]); 220 collection.add(new Backbone.Model({id: 1}), {at: 5}); 221 222 assert.equal(collection.pluck('id').join(' '), '2 3 1'); 223 }); 224 225 QUnit.test("can't add model to collection twice", function(assert) { 226 var collection = new Backbone.Collection([{id: 1}, {id: 2}, {id: 1}, {id: 2}, {id: 3}]); 227 assert.equal(collection.pluck('id').join(' '), '1 2 3'); 228 }); 229 230 QUnit.test("can't add different model with same id to collection twice", function(assert) { 231 assert.expect(1); 232 var collection = new Backbone.Collection; 233 collection.unshift({id: 101}); 234 collection.add({id: 101}); 235 assert.equal(collection.length, 1); 236 }); 237 238 QUnit.test('merge in duplicate models with {merge: true}', function(assert) { 239 assert.expect(3); 240 var collection = new Backbone.Collection; 241 collection.add([{id: 1, name: 'Moe'}, {id: 2, name: 'Curly'}, {id: 3, name: 'Larry'}]); 242 collection.add({id: 1, name: 'Moses'}); 243 assert.equal(collection.first().get('name'), 'Moe'); 244 collection.add({id: 1, name: 'Moses'}, {merge: true}); 245 assert.equal(collection.first().get('name'), 'Moses'); 246 collection.add({id: 1, name: 'Tim'}, {merge: true, silent: true}); 247 assert.equal(collection.first().get('name'), 'Tim'); 248 }); 249 250 QUnit.test('add model to multiple collections', function(assert) { 251 assert.expect(10); 252 var counter = 0; 253 var m = new Backbone.Model({id: 10, label: 'm'}); 254 m.on('add', function(model, collection) { 255 counter++; 256 assert.equal(m, model); 257 if (counter > 1) { 258 assert.equal(collection, col2); 259 } else { 260 assert.equal(collection, col1); 261 } 262 }); 263 var col1 = new Backbone.Collection([]); 264 col1.on('add', function(model, collection) { 265 assert.equal(m, model); 266 assert.equal(col1, collection); 267 }); 268 var col2 = new Backbone.Collection([]); 269 col2.on('add', function(model, collection) { 270 assert.equal(m, model); 271 assert.equal(col2, collection); 272 }); 273 col1.add(m); 274 assert.equal(m.collection, col1); 275 col2.add(m); 276 assert.equal(m.collection, col1); 277 }); 278 279 QUnit.test('add model with parse', function(assert) { 280 assert.expect(1); 281 var Model = Backbone.Model.extend({ 282 parse: function(obj) { 283 obj.value += 1; 284 return obj; 285 } 286 }); 287 288 var Col = Backbone.Collection.extend({model: Model}); 289 var collection = new Col; 290 collection.add({value: 1}, {parse: true}); 291 assert.equal(collection.at(0).get('value'), 2); 292 }); 293 294 QUnit.test('add with parse and merge', function(assert) { 295 var collection = new Backbone.Collection(); 296 collection.parse = function(attrs) { 297 return _.map(attrs, function(model) { 298 if (model.model) return model.model; 299 return model; 300 }); 301 }; 302 collection.add({id: 1}); 303 collection.add({model: {id: 1, name: 'Alf'}}, {parse: true, merge: true}); 304 assert.equal(collection.first().get('name'), 'Alf'); 305 }); 306 307 QUnit.test('add model to collection with sort()-style comparator', function(assert) { 308 assert.expect(3); 309 var collection = new Backbone.Collection; 310 collection.comparator = function(m1, m2) { 311 return m1.get('name') < m2.get('name') ? -1 : 1; 312 }; 313 var tom = new Backbone.Model({name: 'Tom'}); 314 var rob = new Backbone.Model({name: 'Rob'}); 315 var tim = new Backbone.Model({name: 'Tim'}); 316 collection.add(tom); 317 collection.add(rob); 318 collection.add(tim); 319 assert.equal(collection.indexOf(rob), 0); 320 assert.equal(collection.indexOf(tim), 1); 321 assert.equal(collection.indexOf(tom), 2); 322 }); 323 324 QUnit.test('comparator that depends on `this`', function(assert) { 325 assert.expect(2); 326 var collection = new Backbone.Collection; 327 collection.negative = function(num) { 328 return -num; 329 }; 330 collection.comparator = function(model) { 331 return this.negative(model.id); 332 }; 333 collection.add([{id: 1}, {id: 2}, {id: 3}]); 334 assert.deepEqual(collection.pluck('id'), [3, 2, 1]); 335 collection.comparator = function(m1, m2) { 336 return this.negative(m2.id) - this.negative(m1.id); 337 }; 338 collection.sort(); 339 assert.deepEqual(collection.pluck('id'), [1, 2, 3]); 340 }); 341 342 QUnit.test('remove', function(assert) { 343 assert.expect(12); 344 var removed = null; 345 var result = null; 346 col.on('remove', function(model, collection, options) { 347 removed = model.get('label'); 348 assert.equal(options.index, 3); 349 assert.equal(collection.get(model), undefined, '#3693: model cannot be fetched from collection'); 350 }); 351 result = col.remove(d); 352 assert.equal(removed, 'd'); 353 assert.strictEqual(result, d); 354 //if we try to remove d again, it's not going to actually get removed 355 result = col.remove(d); 356 assert.strictEqual(result, undefined); 357 assert.equal(col.length, 3); 358 assert.equal(col.first(), a); 359 col.off(); 360 result = col.remove([c, d]); 361 assert.equal(result.length, 1, 'only returns removed models'); 362 assert.equal(result[0], c, 'only returns removed models'); 363 result = col.remove([c, b]); 364 assert.equal(result.length, 1, 'only returns removed models'); 365 assert.equal(result[0], b, 'only returns removed models'); 366 result = col.remove([]); 367 assert.deepEqual(result, [], 'returns empty array when nothing removed'); 368 }); 369 370 QUnit.test('add and remove return values', function(assert) { 371 assert.expect(13); 372 var Even = Backbone.Model.extend({ 373 validate: function(attrs) { 374 if (attrs.id % 2 !== 0) return 'odd'; 375 } 376 }); 377 var collection = new Backbone.Collection; 378 collection.model = Even; 379 380 var list = collection.add([{id: 2}, {id: 4}], {validate: true}); 381 assert.equal(list.length, 2); 382 assert.ok(list[0] instanceof Backbone.Model); 383 assert.equal(list[1], collection.last()); 384 assert.equal(list[1].get('id'), 4); 385 386 list = collection.add([{id: 3}, {id: 6}], {validate: true}); 387 assert.equal(collection.length, 3); 388 assert.equal(list[0], false); 389 assert.equal(list[1].get('id'), 6); 390 391 var result = collection.add({id: 6}); 392 assert.equal(result.cid, list[1].cid); 393 394 result = collection.remove({id: 6}); 395 assert.equal(collection.length, 2); 396 assert.equal(result.id, 6); 397 398 list = collection.remove([{id: 2}, {id: 8}]); 399 assert.equal(collection.length, 1); 400 assert.equal(list[0].get('id'), 2); 401 assert.equal(list[1], null); 402 }); 403 404 QUnit.test('shift and pop', function(assert) { 405 assert.expect(2); 406 var collection = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]); 407 assert.equal(collection.shift().get('a'), 'a'); 408 assert.equal(collection.pop().get('c'), 'c'); 409 }); 410 411 QUnit.test('slice', function(assert) { 412 assert.expect(2); 413 var collection = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]); 414 var array = collection.slice(1, 3); 415 assert.equal(array.length, 2); 416 assert.equal(array[0].get('b'), 'b'); 417 }); 418 419 QUnit.test('events are unbound on remove', function(assert) { 420 assert.expect(3); 421 var counter = 0; 422 var dj = new Backbone.Model(); 423 var emcees = new Backbone.Collection([dj]); 424 emcees.on('change', function(){ counter++; }); 425 dj.set({name: 'Kool'}); 426 assert.equal(counter, 1); 427 emcees.reset([]); 428 assert.equal(dj.collection, undefined); 429 dj.set({name: 'Shadow'}); 430 assert.equal(counter, 1); 431 }); 432 433 QUnit.test('remove in multiple collections', function(assert) { 434 assert.expect(7); 435 var modelData = { 436 id: 5, 437 title: 'Othello' 438 }; 439 var passed = false; 440 var m1 = new Backbone.Model(modelData); 441 var m2 = new Backbone.Model(modelData); 442 m2.on('remove', function() { 443 passed = true; 444 }); 445 var col1 = new Backbone.Collection([m1]); 446 var col2 = new Backbone.Collection([m2]); 447 assert.notEqual(m1, m2); 448 assert.ok(col1.length === 1); 449 assert.ok(col2.length === 1); 450 col1.remove(m1); 451 assert.equal(passed, false); 452 assert.ok(col1.length === 0); 453 col2.remove(m1); 454 assert.ok(col2.length === 0); 455 assert.equal(passed, true); 456 }); 457 458 QUnit.test('remove same model in multiple collection', function(assert) { 459 assert.expect(16); 460 var counter = 0; 461 var m = new Backbone.Model({id: 5, title: 'Othello'}); 462 m.on('remove', function(model, collection) { 463 counter++; 464 assert.equal(m, model); 465 if (counter > 1) { 466 assert.equal(collection, col1); 467 } else { 468 assert.equal(collection, col2); 469 } 470 }); 471 var col1 = new Backbone.Collection([m]); 472 col1.on('remove', function(model, collection) { 473 assert.equal(m, model); 474 assert.equal(col1, collection); 475 }); 476 var col2 = new Backbone.Collection([m]); 477 col2.on('remove', function(model, collection) { 478 assert.equal(m, model); 479 assert.equal(col2, collection); 480 }); 481 assert.equal(col1, m.collection); 482 col2.remove(m); 483 assert.ok(col2.length === 0); 484 assert.ok(col1.length === 1); 485 assert.equal(counter, 1); 486 assert.equal(col1, m.collection); 487 col1.remove(m); 488 assert.equal(null, m.collection); 489 assert.ok(col1.length === 0); 490 assert.equal(counter, 2); 491 }); 492 493 QUnit.test('model destroy removes from all collections', function(assert) { 494 assert.expect(3); 495 var m = new Backbone.Model({id: 5, title: 'Othello'}); 496 m.sync = function(method, model, options) { options.success(); }; 497 var col1 = new Backbone.Collection([m]); 498 var col2 = new Backbone.Collection([m]); 499 m.destroy(); 500 assert.ok(col1.length === 0); 501 assert.ok(col2.length === 0); 502 assert.equal(undefined, m.collection); 503 }); 504 505 QUnit.test('Collection: non-persisted model destroy removes from all collections', function(assert) { 506 assert.expect(3); 507 var m = new Backbone.Model({title: 'Othello'}); 508 m.sync = function(method, model, options) { throw 'should not be called'; }; 509 var col1 = new Backbone.Collection([m]); 510 var col2 = new Backbone.Collection([m]); 511 m.destroy(); 512 assert.ok(col1.length === 0); 513 assert.ok(col2.length === 0); 514 assert.equal(undefined, m.collection); 515 }); 516 517 QUnit.test('fetch', function(assert) { 518 assert.expect(4); 519 var collection = new Backbone.Collection; 520 collection.url = '/test'; 521 collection.fetch(); 522 assert.equal(this.syncArgs.method, 'read'); 523 assert.equal(this.syncArgs.model, collection); 524 assert.equal(this.syncArgs.options.parse, true); 525 526 collection.fetch({parse: false}); 527 assert.equal(this.syncArgs.options.parse, false); 528 }); 529 530 QUnit.test('fetch with an error response triggers an error event', function(assert) { 531 assert.expect(1); 532 var collection = new Backbone.Collection(); 533 collection.on('error', function() { 534 assert.ok(true); 535 }); 536 collection.sync = function(method, model, options) { options.error(); }; 537 collection.fetch(); 538 }); 539 540 QUnit.test('#3283 - fetch with an error response calls error with context', function(assert) { 541 assert.expect(1); 542 var collection = new Backbone.Collection(); 543 var obj = {}; 544 var options = { 545 context: obj, 546 error: function() { 547 assert.equal(this, obj); 548 } 549 }; 550 collection.sync = function(method, model, opts) { 551 opts.error.call(opts.context); 552 }; 553 collection.fetch(options); 554 }); 555 556 QUnit.test('ensure fetch only parses once', function(assert) { 557 assert.expect(1); 558 var collection = new Backbone.Collection; 559 var counter = 0; 560 collection.parse = function(models) { 561 counter++; 562 return models; 563 }; 564 collection.url = '/test'; 565 collection.fetch(); 566 this.syncArgs.options.success([]); 567 assert.equal(counter, 1); 568 }); 569 570 QUnit.test('create', function(assert) { 571 assert.expect(4); 572 var collection = new Backbone.Collection; 573 collection.url = '/test'; 574 var model = collection.create({label: 'f'}, {wait: true}); 575 assert.equal(this.syncArgs.method, 'create'); 576 assert.equal(this.syncArgs.model, model); 577 assert.equal(model.get('label'), 'f'); 578 assert.equal(model.collection, collection); 579 }); 580 581 QUnit.test('create with validate:true enforces validation', function(assert) { 582 assert.expect(3); 583 var ValidatingModel = Backbone.Model.extend({ 584 validate: function(attrs) { 585 return 'fail'; 586 } 587 }); 588 var ValidatingCollection = Backbone.Collection.extend({ 589 model: ValidatingModel 590 }); 591 var collection = new ValidatingCollection(); 592 collection.on('invalid', function(coll, error, options) { 593 assert.equal(error, 'fail'); 594 assert.equal(options.validationError, 'fail'); 595 }); 596 assert.equal(collection.create({foo: 'bar'}, {validate: true}), false); 597 }); 598 599 QUnit.test('create will pass extra options to success callback', function(assert) { 600 assert.expect(1); 601 var Model = Backbone.Model.extend({ 602 sync: function(method, model, options) { 603 _.extend(options, {specialSync: true}); 604 return Backbone.Model.prototype.sync.call(this, method, model, options); 605 } 606 }); 607 608 var Collection = Backbone.Collection.extend({ 609 model: Model, 610 url: '/test' 611 }); 612 613 var collection = new Collection; 614 615 var success = function(model, response, options) { 616 assert.ok(options.specialSync, 'Options were passed correctly to callback'); 617 }; 618 619 collection.create({}, {success: success}); 620 this.ajaxSettings.success(); 621 }); 622 623 QUnit.test('create with wait:true should not call collection.parse', function(assert) { 624 assert.expect(0); 625 var Collection = Backbone.Collection.extend({ 626 url: '/test', 627 parse: function() { 628 assert.ok(false); 629 } 630 }); 631 632 var collection = new Collection; 633 634 collection.create({}, {wait: true}); 635 this.ajaxSettings.success(); 636 }); 637 638 QUnit.test('a failing create returns model with errors', function(assert) { 639 var ValidatingModel = Backbone.Model.extend({ 640 validate: function(attrs) { 641 return 'fail'; 642 } 643 }); 644 var ValidatingCollection = Backbone.Collection.extend({ 645 model: ValidatingModel 646 }); 647 var collection = new ValidatingCollection(); 648 var m = collection.create({foo: 'bar'}); 649 assert.equal(m.validationError, 'fail'); 650 assert.equal(collection.length, 1); 651 }); 652 653 QUnit.test('initialize', function(assert) { 654 assert.expect(1); 655 var Collection = Backbone.Collection.extend({ 656 initialize: function() { 657 this.one = 1; 658 } 659 }); 660 var coll = new Collection; 661 assert.equal(coll.one, 1); 662 }); 663 664 QUnit.test('preinitialize', function(assert) { 665 assert.expect(1); 666 var Collection = Backbone.Collection.extend({ 667 preinitialize: function() { 668 this.one = 1; 669 } 670 }); 671 var coll = new Collection; 672 assert.equal(coll.one, 1); 673 }); 674 675 QUnit.test('preinitialize occurs before the collection is set up', function(assert) { 676 assert.expect(2); 677 var Collection = Backbone.Collection.extend({ 678 preinitialize: function() { 679 assert.notEqual(this.model, FooModel); 680 } 681 }); 682 var FooModel = Backbone.Model.extend({id: 'foo'}); 683 var coll = new Collection({}, { 684 model: FooModel 685 }); 686 assert.equal(coll.model, FooModel); 687 }); 688 689 QUnit.test('toJSON', function(assert) { 690 assert.expect(1); 691 assert.equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]'); 692 }); 693 694 QUnit.test('where and findWhere', function(assert) { 695 assert.expect(8); 696 var model = new Backbone.Model({a: 1}); 697 var coll = new Backbone.Collection([ 698 model, 699 {a: 1}, 700 {a: 1, b: 2}, 701 {a: 2, b: 2}, 702 {a: 3} 703 ]); 704 assert.equal(coll.where({a: 1}).length, 3); 705 assert.equal(coll.where({a: 2}).length, 1); 706 assert.equal(coll.where({a: 3}).length, 1); 707 assert.equal(coll.where({b: 1}).length, 0); 708 assert.equal(coll.where({b: 2}).length, 2); 709 assert.equal(coll.where({a: 1, b: 2}).length, 1); 710 assert.equal(coll.findWhere({a: 1}), model); 711 assert.equal(coll.findWhere({a: 4}), void 0); 712 }); 713 714 QUnit.test('mixin', function(assert) { 715 Backbone.Collection.mixin({ 716 sum: function(models, iteratee) { 717 return _.reduce(models, function(s, m) { 718 return s + iteratee(m); 719 }, 0); 720 } 721 }); 722 723 var coll = new Backbone.Collection([ 724 {a: 1}, 725 {a: 1, b: 2}, 726 {a: 2, b: 2}, 727 {a: 3} 728 ]); 729 730 assert.equal(coll.sum(function(m) { 731 return m.get('a'); 732 }), 7); 733 }); 734 735 QUnit.test('Underscore methods', function(assert) { 736 assert.expect(21); 737 assert.equal(col.map(function(model){ return model.get('label'); }).join(' '), 'a b c d'); 738 assert.equal(col.some(function(model){ return model.id === 100; }), false); 739 assert.equal(col.some(function(model){ return model.id === 0; }), true); 740 assert.equal(col.reduce(function(m1, m2) {return m1.id > m2.id ? m1 : m2;}).id, 3); 741 assert.equal(col.reduceRight(function(m1, m2) {return m1.id > m2.id ? m1 : m2;}).id, 3); 742 assert.equal(col.indexOf(b), 1); 743 assert.equal(col.size(), 4); 744 assert.equal(col.rest().length, 3); 745 assert.ok(!_.includes(col.rest(), a)); 746 assert.ok(_.includes(col.rest(), d)); 747 assert.ok(!col.isEmpty()); 748 assert.ok(!_.includes(col.without(d), d)); 749 750 var wrapped = col.chain(); 751 assert.equal(wrapped.map('id').max().value(), 3); 752 assert.equal(wrapped.map('id').min().value(), 0); 753 assert.deepEqual(wrapped 754 .filter(function(o){ return o.id % 2 === 0; }) 755 .map(function(o){ return o.id * 2; }) 756 .value(), 757 [4, 0]); 758 assert.deepEqual(col.difference([c, d]), [a, b]); 759 assert.ok(col.includes(col.sample())); 760 761 var first = col.first(); 762 assert.deepEqual(col.groupBy(function(model){ return model.id; })[first.id], [first]); 763 assert.deepEqual(col.countBy(function(model){ return model.id; }), {0: 1, 1: 1, 2: 1, 3: 1}); 764 assert.deepEqual(col.sortBy(function(model){ return model.id; })[0], col.at(3)); 765 assert.ok(col.indexBy('id')[first.id] === first); 766 }); 767 768 QUnit.test('Underscore methods with object-style and property-style iteratee', function(assert) { 769 assert.expect(26); 770 var model = new Backbone.Model({a: 4, b: 1, e: 3}); 771 var coll = new Backbone.Collection([ 772 {a: 1, b: 1}, 773 {a: 2, b: 1, c: 1}, 774 {a: 3, b: 1}, 775 model 776 ]); 777 assert.equal(coll.find({a: 0}), undefined); 778 assert.deepEqual(coll.find({a: 4}), model); 779 assert.equal(coll.find('d'), undefined); 780 assert.deepEqual(coll.find('e'), model); 781 assert.equal(coll.filter({a: 0}), false); 782 assert.deepEqual(coll.filter({a: 4}), [model]); 783 assert.equal(coll.some({a: 0}), false); 784 assert.equal(coll.some({a: 1}), true); 785 assert.equal(coll.reject({a: 0}).length, 4); 786 assert.deepEqual(coll.reject({a: 4}), _.without(coll.models, model)); 787 assert.equal(coll.every({a: 0}), false); 788 assert.equal(coll.every({b: 1}), true); 789 assert.deepEqual(coll.partition({a: 0})[0], []); 790 assert.deepEqual(coll.partition({a: 0})[1], coll.models); 791 assert.deepEqual(coll.partition({a: 4})[0], [model]); 792 assert.deepEqual(coll.partition({a: 4})[1], _.without(coll.models, model)); 793 assert.deepEqual(coll.map({a: 2}), [false, true, false, false]); 794 assert.deepEqual(coll.map('a'), [1, 2, 3, 4]); 795 assert.deepEqual(coll.sortBy('a')[3], model); 796 assert.deepEqual(coll.sortBy('e')[0], model); 797 assert.deepEqual(coll.countBy({a: 4}), {false: 3, true: 1}); 798 assert.deepEqual(coll.countBy('d'), {undefined: 4}); 799 assert.equal(coll.findIndex({b: 1}), 0); 800 assert.equal(coll.findIndex({b: 9}), -1); 801 assert.equal(coll.findLastIndex({b: 1}), 3); 802 assert.equal(coll.findLastIndex({b: 9}), -1); 803 }); 804 805 QUnit.test('reset', function(assert) { 806 assert.expect(16); 807 808 var resetCount = 0; 809 var models = col.models; 810 col.on('reset', function() { resetCount += 1; }); 811 col.reset([]); 812 assert.equal(resetCount, 1); 813 assert.equal(col.length, 0); 814 assert.equal(col.last(), null); 815 col.reset(models); 816 assert.equal(resetCount, 2); 817 assert.equal(col.length, 4); 818 assert.equal(col.last(), d); 819 col.reset(_.map(models, function(m){ return m.attributes; })); 820 assert.equal(resetCount, 3); 821 assert.equal(col.length, 4); 822 assert.ok(col.last() !== d); 823 assert.ok(_.isEqual(col.last().attributes, d.attributes)); 824 col.reset(); 825 assert.equal(col.length, 0); 826 assert.equal(resetCount, 4); 827 828 var f = new Backbone.Model({id: 20, label: 'f'}); 829 col.reset([undefined, f]); 830 assert.equal(col.length, 2); 831 assert.equal(resetCount, 5); 832 833 col.reset(new Array(4)); 834 assert.equal(col.length, 4); 835 assert.equal(resetCount, 6); 836 }); 837 838 QUnit.test('reset with different values', function(assert) { 839 var collection = new Backbone.Collection({id: 1}); 840 collection.reset({id: 1, a: 1}); 841 assert.equal(collection.get(1).get('a'), 1); 842 }); 843 844 QUnit.test('same references in reset', function(assert) { 845 var model = new Backbone.Model({id: 1}); 846 var collection = new Backbone.Collection({id: 1}); 847 collection.reset(model); 848 assert.equal(collection.get(1), model); 849 }); 850 851 QUnit.test('reset passes caller options', function(assert) { 852 assert.expect(3); 853 var Model = Backbone.Model.extend({ 854 initialize: function(attrs, options) { 855 this.modelParameter = options.modelParameter; 856 } 857 }); 858 var collection = new (Backbone.Collection.extend({model: Model}))(); 859 collection.reset([{astring: 'green', anumber: 1}, {astring: 'blue', anumber: 2}], {modelParameter: 'model parameter'}); 860 assert.equal(collection.length, 2); 861 collection.each(function(model) { 862 assert.equal(model.modelParameter, 'model parameter'); 863 }); 864 }); 865 866 QUnit.test('reset does not alter options by reference', function(assert) { 867 assert.expect(2); 868 var collection = new Backbone.Collection([{id: 1}]); 869 var origOpts = {}; 870 collection.on('reset', function(coll, opts){ 871 assert.equal(origOpts.previousModels, undefined); 872 assert.equal(opts.previousModels[0].id, 1); 873 }); 874 collection.reset([], origOpts); 875 }); 876 877 QUnit.test('trigger custom events on models', function(assert) { 878 assert.expect(1); 879 var fired = null; 880 a.on('custom', function() { fired = true; }); 881 a.trigger('custom'); 882 assert.equal(fired, true); 883 }); 884 885 QUnit.test('add does not alter arguments', function(assert) { 886 assert.expect(2); 887 var attrs = {}; 888 var models = [attrs]; 889 new Backbone.Collection().add(models); 890 assert.equal(models.length, 1); 891 assert.ok(attrs === models[0]); 892 }); 893 894 QUnit.test('#714: access `model.collection` in a brand new model.', function(assert) { 895 assert.expect(2); 896 var collection = new Backbone.Collection; 897 collection.url = '/test'; 898 var Model = Backbone.Model.extend({ 899 set: function(attrs) { 900 assert.equal(attrs.prop, 'value'); 901 assert.equal(this.collection, collection); 902 return this; 903 } 904 }); 905 collection.model = Model; 906 collection.create({prop: 'value'}); 907 }); 908 909 QUnit.test('#574, remove its own reference to the .models array.', function(assert) { 910 assert.expect(2); 911 var collection = new Backbone.Collection([ 912 {id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6} 913 ]); 914 assert.equal(collection.length, 6); 915 collection.remove(collection.models); 916 assert.equal(collection.length, 0); 917 }); 918 919 QUnit.test('#861, adding models to a collection which do not pass validation, with validate:true', function(assert) { 920 assert.expect(2); 921 var Model = Backbone.Model.extend({ 922 validate: function(attrs) { 923 if (attrs.id === 3) return "id can't be 3"; 924 } 925 }); 926 927 var Collection = Backbone.Collection.extend({ 928 model: Model 929 }); 930 931 var collection = new Collection; 932 collection.on('invalid', function() { assert.ok(true); }); 933 934 collection.add([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}], {validate: true}); 935 assert.deepEqual(collection.pluck('id'), [1, 2, 4, 5, 6]); 936 }); 937 938 QUnit.test('Invalid models are discarded with validate:true.', function(assert) { 939 assert.expect(5); 940 var collection = new Backbone.Collection; 941 collection.on('test', function() { assert.ok(true); }); 942 collection.model = Backbone.Model.extend({ 943 validate: function(attrs){ if (!attrs.valid) return 'invalid'; } 944 }); 945 var model = new collection.model({id: 1, valid: true}); 946 collection.add([model, {id: 2}], {validate: true}); 947 model.trigger('test'); 948 assert.ok(collection.get(model.cid)); 949 assert.ok(collection.get(1)); 950 assert.ok(!collection.get(2)); 951 assert.equal(collection.length, 1); 952 }); 953 954 QUnit.test('multiple copies of the same model', function(assert) { 955 assert.expect(3); 956 var collection = new Backbone.Collection(); 957 var model = new Backbone.Model(); 958 collection.add([model, model]); 959 assert.equal(collection.length, 1); 960 collection.add([{id: 1}, {id: 1}]); 961 assert.equal(collection.length, 2); 962 assert.equal(collection.last().id, 1); 963 }); 964 965 QUnit.test('#964 - collection.get return inconsistent', function(assert) { 966 assert.expect(2); 967 var collection = new Backbone.Collection(); 968 assert.ok(collection.get(null) === undefined); 969 assert.ok(collection.get() === undefined); 970 }); 971 972 QUnit.test('#1112 - passing options.model sets collection.model', function(assert) { 973 assert.expect(2); 974 var Model = Backbone.Model.extend({}); 975 var collection = new Backbone.Collection([{id: 1}], {model: Model}); 976 assert.ok(collection.model === Model); 977 assert.ok(collection.at(0) instanceof Model); 978 }); 979 980 QUnit.test('null and undefined are invalid ids.', function(assert) { 981 assert.expect(2); 982 var model = new Backbone.Model({id: 1}); 983 var collection = new Backbone.Collection([model]); 984 model.set({id: null}); 985 assert.ok(!collection.get('null')); 986 model.set({id: 1}); 987 model.set({id: undefined}); 988 assert.ok(!collection.get('undefined')); 989 }); 990 991 QUnit.test('falsy comparator', function(assert) { 992 assert.expect(4); 993 var Col = Backbone.Collection.extend({ 994 comparator: function(model){ return model.id; } 995 }); 996 var collection = new Col(); 997 var colFalse = new Col(null, {comparator: false}); 998 var colNull = new Col(null, {comparator: null}); 999 var colUndefined = new Col(null, {comparator: undefined}); 1000 assert.ok(collection.comparator); 1001 assert.ok(!colFalse.comparator); 1002 assert.ok(!colNull.comparator); 1003 assert.ok(colUndefined.comparator); 1004 }); 1005 1006 QUnit.test('#1355 - `options` is passed to success callbacks', function(assert) { 1007 assert.expect(2); 1008 var m = new Backbone.Model({x: 1}); 1009 var collection = new Backbone.Collection(); 1010 var opts = { 1011 opts: true, 1012 success: function(coll, resp, options) { 1013 assert.ok(options.opts); 1014 } 1015 }; 1016 collection.sync = m.sync = function( method, coll, options ){ 1017 options.success({}); 1018 }; 1019 collection.fetch(opts); 1020 collection.create(m, opts); 1021 }); 1022 1023 QUnit.test("#1412 - Trigger 'request' and 'sync' events.", function(assert) { 1024 assert.expect(4); 1025 var collection = new Backbone.Collection; 1026 collection.url = '/test'; 1027 Backbone.ajax = function(settings){ settings.success(); }; 1028 1029 collection.on('request', function(obj, xhr, options) { 1030 assert.ok(obj === collection, "collection has correct 'request' event after fetching"); 1031 }); 1032 collection.on('sync', function(obj, response, options) { 1033 assert.ok(obj === collection, "collection has correct 'sync' event after fetching"); 1034 }); 1035 collection.fetch(); 1036 collection.off(); 1037 1038 collection.on('request', function(obj, xhr, options) { 1039 assert.ok(obj === collection.get(1), "collection has correct 'request' event after one of its models save"); 1040 }); 1041 collection.on('sync', function(obj, response, options) { 1042 assert.ok(obj === collection.get(1), "collection has correct 'sync' event after one of its models save"); 1043 }); 1044 collection.create({id: 1}); 1045 collection.off(); 1046 }); 1047 1048 QUnit.test('#3283 - fetch, create calls success with context', function(assert) { 1049 assert.expect(2); 1050 var collection = new Backbone.Collection; 1051 collection.url = '/test'; 1052 Backbone.ajax = function(settings) { 1053 settings.success.call(settings.context); 1054 }; 1055 var obj = {}; 1056 var options = { 1057 context: obj, 1058 success: function() { 1059 assert.equal(this, obj); 1060 } 1061 }; 1062 1063 collection.fetch(options); 1064 collection.create({id: 1}, options); 1065 }); 1066 1067 QUnit.test('#1447 - create with wait adds model.', function(assert) { 1068 assert.expect(1); 1069 var collection = new Backbone.Collection; 1070 var model = new Backbone.Model; 1071 model.sync = function(method, m, options){ options.success(); }; 1072 collection.on('add', function(){ assert.ok(true); }); 1073 collection.create(model, {wait: true}); 1074 }); 1075 1076 QUnit.test('#1448 - add sorts collection after merge.', function(assert) { 1077 assert.expect(1); 1078 var collection = new Backbone.Collection([ 1079 {id: 1, x: 1}, 1080 {id: 2, x: 2} 1081 ]); 1082 collection.comparator = function(model){ return model.get('x'); }; 1083 collection.add({id: 1, x: 3}, {merge: true}); 1084 assert.deepEqual(collection.pluck('id'), [2, 1]); 1085 }); 1086 1087 QUnit.test('#1655 - groupBy can be used with a string argument.', function(assert) { 1088 assert.expect(3); 1089 var collection = new Backbone.Collection([{x: 1}, {x: 2}]); 1090 var grouped = collection.groupBy('x'); 1091 assert.strictEqual(_.keys(grouped).length, 2); 1092 assert.strictEqual(grouped[1][0].get('x'), 1); 1093 assert.strictEqual(grouped[2][0].get('x'), 2); 1094 }); 1095 1096 QUnit.test('#1655 - sortBy can be used with a string argument.', function(assert) { 1097 assert.expect(1); 1098 var collection = new Backbone.Collection([{x: 3}, {x: 1}, {x: 2}]); 1099 var values = _.map(collection.sortBy('x'), function(model) { 1100 return model.get('x'); 1101 }); 1102 assert.deepEqual(values, [1, 2, 3]); 1103 }); 1104 1105 QUnit.test('#1604 - Removal during iteration.', function(assert) { 1106 assert.expect(0); 1107 var collection = new Backbone.Collection([{}, {}]); 1108 collection.on('add', function() { 1109 collection.at(0).destroy(); 1110 }); 1111 collection.add({}, {at: 0}); 1112 }); 1113 1114 QUnit.test('#1638 - `sort` during `add` triggers correctly.', function(assert) { 1115 var collection = new Backbone.Collection; 1116 collection.comparator = function(model) { return model.get('x'); }; 1117 var added = []; 1118 collection.on('add', function(model) { 1119 model.set({x: 3}); 1120 collection.sort(); 1121 added.push(model.id); 1122 }); 1123 collection.add([{id: 1, x: 1}, {id: 2, x: 2}]); 1124 assert.deepEqual(added, [1, 2]); 1125 }); 1126 1127 QUnit.test('fetch parses models by default', function(assert) { 1128 assert.expect(1); 1129 var model = {}; 1130 var Collection = Backbone.Collection.extend({ 1131 url: 'test', 1132 model: Backbone.Model.extend({ 1133 parse: function(resp) { 1134 assert.strictEqual(resp, model); 1135 } 1136 }) 1137 }); 1138 new Collection().fetch(); 1139 this.ajaxSettings.success([model]); 1140 }); 1141 1142 QUnit.test("`sort` shouldn't always fire on `add`", function(assert) { 1143 assert.expect(1); 1144 var collection = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}], { 1145 comparator: 'id' 1146 }); 1147 collection.sort = function(){ assert.ok(true); }; 1148 collection.add([]); 1149 collection.add({id: 1}); 1150 collection.add([{id: 2}, {id: 3}]); 1151 collection.add({id: 4}); 1152 }); 1153 1154 QUnit.test('#1407 parse option on constructor parses collection and models', function(assert) { 1155 assert.expect(2); 1156 var model = { 1157 namespace: [{id: 1}, {id: 2}] 1158 }; 1159 var Collection = Backbone.Collection.extend({ 1160 model: Backbone.Model.extend({ 1161 parse: function(m) { 1162 m.name = 'test'; 1163 return m; 1164 } 1165 }), 1166 parse: function(m) { 1167 return m.namespace; 1168 } 1169 }); 1170 var collection = new Collection(model, {parse: true}); 1171 1172 assert.equal(collection.length, 2); 1173 assert.equal(collection.at(0).get('name'), 'test'); 1174 }); 1175 1176 QUnit.test('#1407 parse option on reset parses collection and models', function(assert) { 1177 assert.expect(2); 1178 var model = { 1179 namespace: [{id: 1}, {id: 2}] 1180 }; 1181 var Collection = Backbone.Collection.extend({ 1182 model: Backbone.Model.extend({ 1183 parse: function(m) { 1184 m.name = 'test'; 1185 return m; 1186 } 1187 }), 1188 parse: function(m) { 1189 return m.namespace; 1190 } 1191 }); 1192 var collection = new Collection(); 1193 collection.reset(model, {parse: true}); 1194 1195 assert.equal(collection.length, 2); 1196 assert.equal(collection.at(0).get('name'), 'test'); 1197 }); 1198 1199 1200 QUnit.test('Reset includes previous models in triggered event.', function(assert) { 1201 assert.expect(1); 1202 var model = new Backbone.Model(); 1203 var collection = new Backbone.Collection([model]); 1204 collection.on('reset', function(coll, options) { 1205 assert.deepEqual(options.previousModels, [model]); 1206 }); 1207 collection.reset([]); 1208 }); 1209 1210 QUnit.test('set', function(assert) { 1211 var m1 = new Backbone.Model(); 1212 var m2 = new Backbone.Model({id: 2}); 1213 var m3 = new Backbone.Model(); 1214 var collection = new Backbone.Collection([m1, m2]); 1215 1216 // Test add/change/remove events 1217 collection.on('add', function(model) { 1218 assert.strictEqual(model, m3); 1219 }); 1220 collection.on('change', function(model) { 1221 assert.strictEqual(model, m2); 1222 }); 1223 collection.on('remove', function(model) { 1224 assert.strictEqual(model, m1); 1225 }); 1226 1227 // remove: false doesn't remove any models 1228 collection.set([], {remove: false}); 1229 assert.strictEqual(collection.length, 2); 1230 1231 // add: false doesn't add any models 1232 collection.set([m1, m2, m3], {add: false}); 1233 assert.strictEqual(collection.length, 2); 1234 1235 // merge: false doesn't change any models 1236 collection.set([m1, {id: 2, a: 1}], {merge: false}); 1237 assert.strictEqual(m2.get('a'), void 0); 1238 1239 // add: false, remove: false only merges existing models 1240 collection.set([m1, {id: 2, a: 0}, m3, {id: 4}], {add: false, remove: false}); 1241 assert.strictEqual(collection.length, 2); 1242 assert.strictEqual(m2.get('a'), 0); 1243 1244 // default options add/remove/merge as appropriate 1245 collection.set([{id: 2, a: 1}, m3]); 1246 assert.strictEqual(collection.length, 2); 1247 assert.strictEqual(m2.get('a'), 1); 1248 1249 // Test removing models not passing an argument 1250 collection.off('remove').on('remove', function(model) { 1251 assert.ok(model === m2 || model === m3); 1252 }); 1253 collection.set([]); 1254 assert.strictEqual(collection.length, 0); 1255 1256 // Test null models on set doesn't clear collection 1257 collection.off(); 1258 collection.set([{id: 1}]); 1259 collection.set(); 1260 assert.strictEqual(collection.length, 1); 1261 }); 1262 1263 QUnit.test('set with only cids', function(assert) { 1264 assert.expect(3); 1265 var m1 = new Backbone.Model; 1266 var m2 = new Backbone.Model; 1267 var collection = new Backbone.Collection; 1268 collection.set([m1, m2]); 1269 assert.equal(collection.length, 2); 1270 collection.set([m1]); 1271 assert.equal(collection.length, 1); 1272 collection.set([m1, m1, m1, m2, m2], {remove: false}); 1273 assert.equal(collection.length, 2); 1274 }); 1275 1276 QUnit.test('set with only idAttribute', function(assert) { 1277 assert.expect(3); 1278 var m1 = {_id: 1}; 1279 var m2 = {_id: 2}; 1280 var Col = Backbone.Collection.extend({ 1281 model: Backbone.Model.extend({ 1282 idAttribute: '_id' 1283 }) 1284 }); 1285 var collection = new Col; 1286 collection.set([m1, m2]); 1287 assert.equal(collection.length, 2); 1288 collection.set([m1]); 1289 assert.equal(collection.length, 1); 1290 collection.set([m1, m1, m1, m2, m2], {remove: false}); 1291 assert.equal(collection.length, 2); 1292 }); 1293 1294 QUnit.test('set + merge with default values defined', function(assert) { 1295 var Model = Backbone.Model.extend({ 1296 defaults: { 1297 key: 'value' 1298 } 1299 }); 1300 var m = new Model({id: 1}); 1301 var collection = new Backbone.Collection([m], {model: Model}); 1302 assert.equal(collection.first().get('key'), 'value'); 1303 1304 collection.set({id: 1, key: 'other'}); 1305 assert.equal(collection.first().get('key'), 'other'); 1306 1307 collection.set({id: 1, other: 'value'}); 1308 assert.equal(collection.first().get('key'), 'other'); 1309 assert.equal(collection.length, 1); 1310 }); 1311 1312 QUnit.test('merge without mutation', function(assert) { 1313 var Model = Backbone.Model.extend({ 1314 initialize: function(attrs, options) { 1315 if (attrs.child) { 1316 this.set('child', new Model(attrs.child, options), options); 1317 } 1318 } 1319 }); 1320 var Collection = Backbone.Collection.extend({model: Model}); 1321 var data = [{id: 1, child: {id: 2}}]; 1322 var collection = new Collection(data); 1323 assert.equal(collection.first().id, 1); 1324 collection.set(data); 1325 assert.equal(collection.first().id, 1); 1326 collection.set([{id: 2, child: {id: 2}}].concat(data)); 1327 assert.deepEqual(collection.pluck('id'), [2, 1]); 1328 }); 1329 1330 QUnit.test('`set` and model level `parse`', function(assert) { 1331 var Model = Backbone.Model.extend({}); 1332 var Collection = Backbone.Collection.extend({ 1333 model: Model, 1334 parse: function(res) { return _.map(res.models, 'model'); } 1335 }); 1336 var model = new Model({id: 1}); 1337 var collection = new Collection(model); 1338 collection.set({models: [ 1339 {model: {id: 1}}, 1340 {model: {id: 2}} 1341 ]}, {parse: true}); 1342 assert.equal(collection.first(), model); 1343 }); 1344 1345 QUnit.test('`set` data is only parsed once', function(assert) { 1346 var collection = new Backbone.Collection(); 1347 collection.model = Backbone.Model.extend({ 1348 parse: function(data) { 1349 assert.equal(data.parsed, void 0); 1350 data.parsed = true; 1351 return data; 1352 } 1353 }); 1354 collection.set({}, {parse: true}); 1355 }); 1356 1357 QUnit.test('`set` matches input order in the absence of a comparator', function(assert) { 1358 var one = new Backbone.Model({id: 1}); 1359 var two = new Backbone.Model({id: 2}); 1360 var three = new Backbone.Model({id: 3}); 1361 var collection = new Backbone.Collection([one, two, three]); 1362 collection.set([{id: 3}, {id: 2}, {id: 1}]); 1363 assert.deepEqual(collection.models, [three, two, one]); 1364 collection.set([{id: 1}, {id: 2}]); 1365 assert.deepEqual(collection.models, [one, two]); 1366 collection.set([two, three, one]); 1367 assert.deepEqual(collection.models, [two, three, one]); 1368 collection.set([{id: 1}, {id: 2}], {remove: false}); 1369 assert.deepEqual(collection.models, [two, three, one]); 1370 collection.set([{id: 1}, {id: 2}, {id: 3}], {merge: false}); 1371 assert.deepEqual(collection.models, [one, two, three]); 1372 collection.set([three, two, one, {id: 4}], {add: false}); 1373 assert.deepEqual(collection.models, [one, two, three]); 1374 }); 1375 1376 QUnit.test('#1894 - Push should not trigger a sort', function(assert) { 1377 assert.expect(0); 1378 var Collection = Backbone.Collection.extend({ 1379 comparator: 'id', 1380 sort: function() { assert.ok(false); } 1381 }); 1382 new Collection().push({id: 1}); 1383 }); 1384 1385 QUnit.test('#2428 - push duplicate models, return the correct one', function(assert) { 1386 assert.expect(1); 1387 var collection = new Backbone.Collection; 1388 var model1 = collection.push({id: 101}); 1389 var model2 = collection.push({id: 101}); 1390 assert.ok(model2.cid === model1.cid); 1391 }); 1392 1393 QUnit.test('`set` with non-normal id', function(assert) { 1394 var Collection = Backbone.Collection.extend({ 1395 model: Backbone.Model.extend({idAttribute: '_id'}) 1396 }); 1397 var collection = new Collection({_id: 1}); 1398 collection.set([{_id: 1, a: 1}], {add: false}); 1399 assert.equal(collection.first().get('a'), 1); 1400 }); 1401 1402 QUnit.test('#1894 - `sort` can optionally be turned off', function(assert) { 1403 assert.expect(0); 1404 var Collection = Backbone.Collection.extend({ 1405 comparator: 'id', 1406 sort: function() { assert.ok(false); } 1407 }); 1408 new Collection().add({id: 1}, {sort: false}); 1409 }); 1410 1411 QUnit.test('#1915 - `parse` data in the right order in `set`', function(assert) { 1412 var collection = new (Backbone.Collection.extend({ 1413 parse: function(data) { 1414 assert.strictEqual(data.status, 'ok'); 1415 return data.data; 1416 } 1417 })); 1418 var res = {status: 'ok', data: [{id: 1}]}; 1419 collection.set(res, {parse: true}); 1420 }); 1421 1422 QUnit.test('#1939 - `parse` is passed `options`', function(assert) { 1423 var done = assert.async(); 1424 assert.expect(1); 1425 var collection = new (Backbone.Collection.extend({ 1426 url: '/', 1427 parse: function(data, options) { 1428 assert.strictEqual(options.xhr.someHeader, 'headerValue'); 1429 return data; 1430 } 1431 })); 1432 var ajax = Backbone.ajax; 1433 Backbone.ajax = function(params) { 1434 _.defer(params.success, []); 1435 return {someHeader: 'headerValue'}; 1436 }; 1437 collection.fetch({ 1438 success: function() { done(); } 1439 }); 1440 Backbone.ajax = ajax; 1441 }); 1442 1443 QUnit.test('fetch will pass extra options to success callback', function(assert) { 1444 assert.expect(1); 1445 var SpecialSyncCollection = Backbone.Collection.extend({ 1446 url: '/test', 1447 sync: function(method, collection, options) { 1448 _.extend(options, {specialSync: true}); 1449 return Backbone.Collection.prototype.sync.call(this, method, collection, options); 1450 } 1451 }); 1452 1453 var collection = new SpecialSyncCollection(); 1454 1455 var onSuccess = function(coll, resp, options) { 1456 assert.ok(options.specialSync, 'Options were passed correctly to callback'); 1457 }; 1458 1459 collection.fetch({success: onSuccess}); 1460 this.ajaxSettings.success(); 1461 }); 1462 1463 QUnit.test('`add` only `sort`s when necessary', function(assert) { 1464 assert.expect(2); 1465 var collection = new (Backbone.Collection.extend({ 1466 comparator: 'a' 1467 }))([{id: 1}, {id: 2}, {id: 3}]); 1468 collection.on('sort', function() { assert.ok(true); }); 1469 collection.add({id: 4}); // do sort, new model 1470 collection.add({id: 1, a: 1}, {merge: true}); // do sort, comparator change 1471 collection.add({id: 1, b: 1}, {merge: true}); // don't sort, no comparator change 1472 collection.add({id: 1, a: 1}, {merge: true}); // don't sort, no comparator change 1473 collection.add(collection.models); // don't sort, nothing new 1474 collection.add(collection.models, {merge: true}); // don't sort 1475 }); 1476 1477 QUnit.test('`add` only `sort`s when necessary with comparator function', function(assert) { 1478 assert.expect(3); 1479 var collection = new (Backbone.Collection.extend({ 1480 comparator: function(m1, m2) { 1481 return m1.get('a') > m2.get('a') ? 1 : m1.get('a') < m2.get('a') ? -1 : 0; 1482 } 1483 }))([{id: 1}, {id: 2}, {id: 3}]); 1484 collection.on('sort', function() { assert.ok(true); }); 1485 collection.add({id: 4}); // do sort, new model 1486 collection.add({id: 1, a: 1}, {merge: true}); // do sort, model change 1487 collection.add({id: 1, b: 1}, {merge: true}); // do sort, model change 1488 collection.add({id: 1, a: 1}, {merge: true}); // don't sort, no model change 1489 collection.add(collect…
Large files files are truncated, but you can click here to view the full file