]> git.proxmox.com Git - extjs.git/blame - extjs/packages/core/test/specs/util/Collection.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / test / specs / util / Collection.js
CommitLineData
6527f429
DM
1describe("Ext.util.Collection", function() {\r
2 var collection, fakeScope = {};\r
3\r
4 function logEvents (col, log, property) {\r
5 property = property || 'id';\r
6\r
7 col.on({\r
8 beginupdate: function (sender) {\r
9 expect(sender === col).toBe(true);\r
10 log.push('beginupdate');\r
11 },\r
12 add: function (sender, details) {\r
13 expect(sender === col).toBe(true);\r
14 log.push('add ' + Ext.encode(Ext.Array.pluck(details.items, property)) +\r
15 ' at ' + details.at);\r
16 if (details.keys) {\r
17 log[log.length - 1] += ' w/keys ' + Ext.encode(details.keys);\r
18 }\r
19 },\r
20 remove: function (sender, details) {\r
21 expect(sender === col).toBe(true);\r
22 log.push('remove ' + Ext.encode(Ext.Array.pluck(details.items, property)) +\r
23 ' at ' + details.at);\r
24 if (details.keys) {\r
25 log[log.length - 1] += ' w/keys ' + Ext.encode(details.keys);\r
26 }\r
27 },\r
28 endupdate: function (sender) {\r
29 expect(sender === col).toBe(true);\r
30 log.push('endupdate');\r
31 }\r
32 });\r
33 }\r
34\r
35 describe("constructor", function() {\r
36 it("should provide a default getKey implementation", function() {\r
37 collection = new Ext.util.Collection();\r
38\r
39 var item1 = {id: 1, data: 'first item'},\r
40 item2 = {id: 2, data: 'second item'};\r
41\r
42 collection.add(item1);\r
43 collection.add(item2);\r
44\r
45 expect(collection.get(1)).toBe(item1);\r
46 expect(collection.get(2)).toBe(item2);\r
47 });\r
48\r
49 it("should allow a custom getKey implementation", function() {\r
50 collection = new Ext.util.Collection({\r
51 keyFn: function(item) {\r
52 return item.myKey;\r
53 }\r
54 });\r
55\r
56 var item1 = {myKey: 'a', data: 'first item'},\r
57 item2 = {myKey: 'b', data: 'second item'};\r
58\r
59 collection.add(item1, item2);\r
60\r
61 expect(collection.get('a')).toBe(item1);\r
62 expect(collection.get('b')).toBe(item2);\r
63 });\r
64 \r
65 it("should contain the source items when configured with a source", function() {\r
66 var source = new Ext.util.Collection();\r
67 source.add({id: 1}, {id: 2}, {id: 3});\r
68 \r
69 collection = new Ext.util.Collection({\r
70 source: source\r
71 });\r
72 expect(collection.getCount()).toBe(3);\r
73 })\r
74 });\r
75\r
76 describe("iterators", function() {\r
77 var fn, callScope, item1, item2, item3;\r
78\r
79 beforeEach(function() {\r
80 collection = new Ext.util.Collection();\r
81\r
82 fn = jasmine.createSpy('fn');\r
83\r
84 item1 = {id: 1, name: 'first'};\r
85 item2 = {id: 2, name: 'second'};\r
86 item3 = {id: 3, name: 'third'};\r
87\r
88 collection.add([item1, item2, item3]);\r
89 });\r
90\r
91 describe("each", function() {\r
92 it("should call with the correct scope", function() {\r
93 collection.each(function() {\r
94 callScope = this;\r
95 }, fakeScope);\r
96\r
97 expect(callScope).toBe(fakeScope);\r
98 });\r
99\r
100 it("should call the correct number of times", function() {\r
101 collection.each(fn);\r
102\r
103 expect(fn.callCount).toBe(3);\r
104 });\r
105\r
106 it("should be called with each item", function() {\r
107 collection.each(fn);\r
108\r
109 expect(fn).toHaveBeenCalledWith(item1, 0, 3);\r
110 expect(fn).toHaveBeenCalledWith(item2, 1, 3);\r
111 expect(fn).toHaveBeenCalledWith(item3, 2, 3);\r
112 });\r
113 });\r
114\r
115 describe("eachKey", function() {\r
116 it("should be called with the correct scope", function() {\r
117 collection.eachKey(function() {\r
118 callScope = this;\r
119 }, fakeScope);\r
120\r
121 expect(callScope).toBe(fakeScope);\r
122 });\r
123\r
124 it("should call the correct number of times", function() {\r
125 collection.eachKey(fn);\r
126\r
127 expect(fn.callCount).toBe(3);\r
128 });\r
129\r
130 it("should be called with each key", function() {\r
131 collection.eachKey(fn);\r
132\r
133 expect(fn).toHaveBeenCalledWith(1, item1, 0, 3);\r
134 expect(fn).toHaveBeenCalledWith(2, item2, 1, 3);\r
135 expect(fn).toHaveBeenCalledWith(3, item3, 2, 3);\r
136 });\r
137 });\r
138 });\r
139\r
140 describe("adding items", function() {\r
141 var item1, item2, item3, item4;\r
142 beforeEach(function() {\r
143 collection = new Ext.util.Collection();\r
144 item1 = {id: 1};\r
145 item2 = {id: 2};\r
146 item3 = {id: 3};\r
147 item4 = {id: 4};\r
148 });\r
149\r
150 afterEach(function() {\r
151 item1 = item2 = item3 = item4 = null;\r
152 });\r
153\r
154 it("should get the correct count when adding an array", function() {\r
155 collection.add([item1, item2]);\r
156\r
157 expect(collection.getCount()).toBe(2);\r
158 expect(collection.length).toBe(2);\r
159 expect(collection.getAt(0)).toBe(item1);\r
160 expect(collection.getAt(1)).toBe(item2);\r
161 });\r
162\r
163 it("should get the correct count when adding varargs", function() {\r
164 collection.add(item1, item2);\r
165\r
166 expect(collection.getCount()).toBe(2);\r
167 expect(collection.length).toBe(2);\r
168 expect(collection.getAt(0)).toBe(item1);\r
169 expect(collection.getAt(1)).toBe(item2);\r
170 });\r
171\r
172 it("should get the correct count when adding sequentially", function() {\r
173 collection.add(item1);\r
174 collection.add(item2);\r
175\r
176 expect(collection.getCount()).toBe(2);\r
177 expect(collection.length).toBe(2);\r
178 expect(collection.getAt(0)).toBe(item1);\r
179 expect(collection.getAt(1)).toBe(item2);\r
180 });\r
181\r
182 it("should fire the add event", function() {\r
183 var executed = false;\r
184\r
185 collection.on('add', function() {\r
186 executed = true;\r
187 });\r
188\r
189 collection.add(item1);\r
190\r
191 expect(executed).toBe(true);\r
192 });\r
193 \r
194 describe("with replaceAll", function() {\r
195 it("should add when the collection is empty", function() {\r
196 collection.replaceAll(item1);\r
197 expect(collection.getCount()).toBe(1);\r
198 });\r
199 \r
200 it("should remove all existing items", function() {\r
201 collection.add(item1, item2, item3);\r
202 collection.replaceAll(item4);\r
203 expect(collection.getCount()).toBe(1);\r
204 expect(collection.first()).toBe(item4);\r
205 });\r
206 \r
207 it("should remove even when no items are added", function() {\r
208 collection.add(item1, item2, item3);\r
209 collection.setDecoder(function() {\r
210 return false;\r
211 });\r
212 collection.replaceAll(item4);\r
213 expect(collection.getCount()).toBe(0);\r
214 });\r
215 });\r
216\r
217 describe("when sorted", function() {\r
218 var spy, expectPos;\r
219\r
220 beforeEach(function() {\r
221 collection.getSorters().add('id');\r
222 spy = jasmine.createSpy();\r
223 collection.on('sort', spy);\r
224 });\r
225\r
226 afterEach(function() {\r
227 expect(spy).not.toHaveBeenCalled();\r
228 expectPos = spy = null;\r
229 });\r
230\r
231 describe("a single item", function() {\r
232 describe("with no items", function() {\r
233 it("should add the item", function() {\r
234 expectPos = function() {\r
235 expect(collection.length).toBe(1);\r
236 expect(collection.getAt(0)).toBe(item1);\r
237 expect(collection.indexOfKey(1)).toBe(0);\r
238 };\r
239 collection.on('add', expectPos);\r
240 collection.add(item1);\r
241 expectPos();\r
242 });\r
243\r
244 describe("with items", function() {\r
245 it("should put the item in the correct position", function() {\r
246 collection.add(item1, item3);\r
247 expectPos = function() {\r
248 expect(collection.length).toBe(3);\r
249 expect(collection.getAt(1)).toBe(item2);\r
250 expect(collection.indexOfKey(1)).toBe(0);\r
251 expect(collection.indexOfKey(2)).toBe(1);\r
252 expect(collection.indexOfKey(3)).toBe(2);\r
253 };\r
254 collection.on('add', expectPos);\r
255 collection.add(item2);\r
256 expectPos();\r
257 });\r
258 });\r
259 })\r
260 });\r
261\r
262 describe("multiple items", function() {\r
263 describe("with no items", function() {\r
264 it("should insert the items", function() {\r
265 expectPos = function() {\r
266 expect(collection.length).toBe(3);\r
267 expect(collection.getAt(0)).toBe(item1);\r
268 expect(collection.getAt(1)).toBe(item2);\r
269 expect(collection.getAt(2)).toBe(item3);\r
270 expect(collection.indexOfKey(1)).toBe(0);\r
271 expect(collection.indexOfKey(2)).toBe(1);\r
272 expect(collection.indexOfKey(3)).toBe(2);\r
273 };\r
274 collection.on('add', expectPos);\r
275 collection.add([item1, item2, item3]);\r
276 expectPos();\r
277 });\r
278\r
279 it("should sort the added items", function() {\r
280 expectPos = function() {\r
281 expect(collection.length).toBe(3);\r
282 expect(collection.getAt(0)).toBe(item1);\r
283 expect(collection.getAt(1)).toBe(item2);\r
284 expect(collection.getAt(2)).toBe(item3);\r
285 };\r
286 collection.on('add', expectPos)\r
287 collection.add([item3, item1, item2]);\r
288 expectPos();\r
289 });\r
290 });\r
291\r
292 describe("with items", function() {\r
293 it("should insert the items into the correct position", function() {\r
294 collection.add(item3);\r
295 expectPos = function() {\r
296 expect(collection.length).toBe(3);\r
297 expect(collection.getAt(0)).toBe(item1);\r
298 expect(collection.getAt(1)).toBe(item2); \r
299 expect(collection.getAt(2)).toBe(item3);\r
300 expect(collection.indexOfKey(1)).toBe(0);\r
301 expect(collection.indexOfKey(2)).toBe(1);\r
302 expect(collection.indexOfKey(3)).toBe(2);\r
303 };\r
304 collection.on('add', expectPos);\r
305 collection.add(item1, item2);\r
306 expectPos();\r
307 });\r
308\r
309 it("should sort the added items", function() {\r
310 collection.add(item3);\r
311 expectPos = function() {\r
312 expect(collection.length).toBe(3);\r
313 expect(collection.getAt(0)).toBe(item1);\r
314 expect(collection.getAt(1)).toBe(item2);\r
315 expect(collection.getAt(2)).toBe(item3);\r
316 expect(collection.indexOfKey(1)).toBe(0);\r
317 expect(collection.indexOfKey(2)).toBe(1);\r
318 expect(collection.indexOfKey(3)).toBe(2);\r
319 };\r
320 collection.on('add', expectPos);\r
321 collection.add(item2, item1);\r
322 expectPos();\r
323 });\r
324\r
325 it("should insert items in a discontiguous range", function() {\r
326 collection.add(item1, item3);\r
327 var count = 0;\r
328 expectPos = function() {\r
329 expect(collection.length).toBe(4);\r
330 expect(collection.getAt(0)).toBe(item1);\r
331 expect(collection.getAt(1)).toBe(item2);\r
332 expect(collection.getAt(2)).toBe(item3);\r
333 expect(collection.getAt(3)).toBe(item4);\r
334 expect(collection.indexOfKey(1)).toBe(0);\r
335 expect(collection.indexOfKey(2)).toBe(1);\r
336 expect(collection.indexOfKey(3)).toBe(2);\r
337 expect(collection.indexOfKey(4)).toBe(3);\r
338 };\r
339 collection.on('add', function() {\r
340 if (count === 0) {\r
341 expect(collection.length).toBe(4);\r
342 expect(collection.getAt(0)).toBe(item1);\r
343 expect(collection.getAt(1)).toBe(item2);\r
344 expect(collection.getAt(2)).toBe(item3);\r
345 expect(collection.indexOfKey(1)).toBe(0);\r
346 expect(collection.indexOfKey(2)).toBe(1);\r
347 expect(collection.indexOfKey(3)).toBe(2);\r
348 } else {\r
349 expectPos();\r
350 }\r
351 ++count;\r
352 });\r
353 collection.add(item4, item2);\r
354 expectPos();\r
355 });\r
356 });\r
357 });\r
358 });\r
359 });\r
360\r
361 describe("removing items", function() {\r
362 var item1 = {id: 1, name: 'one'},\r
363 item2 = {id: 2, name: 'two'},\r
364 item3 = {id: 3, name: 'three'},\r
365 item4 = {id: 4, name: 'four'},\r
366 item5 = {id: 5, name: 'five'},\r
367 item6 = {id: 6, name: 'six'},\r
368 item7 = {id: 7, name: 'seven'},\r
369 item8 = {id: 8, name: 'eight'},\r
370 item9 = {id: 9, name: 'nine'};\r
371\r
372 beforeEach(function() {\r
373 collection = new Ext.util.Collection();\r
374\r
375 collection.add([\r
376 item1, \r
377 item2, \r
378 item3, \r
379 item4, \r
380 item5, \r
381 item6, \r
382 item7, \r
383 item8, \r
384 item9\r
385 ]);\r
386 });\r
387 \r
388 describe("remove", function() {\r
389 it("should remove a single item", function() {\r
390 collection.remove(item1);\r
391\r
392 expect(collection.getCount()).toBe(8);\r
393 });\r
394 \r
395 it("should return the removed item count", function(){\r
396 expect(collection.remove(item1)).toBe(1);\r
397 });\r
398\r
399 it("should the passed items array", function(){\r
400 collection.remove([item2, item3]);\r
401 expect(collection.getCount()).toBe(7);\r
402 });\r
403\r
404 it("should fire the remove event when passing items array", function () {\r
405 var source = [],\r
406 details = [];\r
407\r
408 collection.on('remove', function (sender, remove) {\r
409 source.push(sender);\r
410 details.push(remove);\r
411 });\r
412\r
413 collection.remove([item2, item3, item6]);\r
414\r
415 expect(source.length).toBe(2);\r
416 expect(source[0] === collection).toBe(true);\r
417 expect(source[1] === collection).toBe(true);\r
418\r
419 expect(details[0].at).toBe(5);\r
420 expect(details[0].items.length).toBe(1);\r
421 expect(details[0].items[0]).toBe(item6);\r
422 expect(details[0].keys.length).toBe(1);\r
423 expect(details[0].keys[0]).toBe(6);\r
424\r
425 expect(details[1].at).toBe(1);\r
426 expect(details[1].items.length).toBe(2);\r
427 expect(details[1].items[0]).toBe(item2);\r
428 expect(details[1].items[1]).toBe(item3);\r
429 expect(details[1].keys.length).toBe(2);\r
430 expect(details[1].keys[0]).toBe(2);\r
431 expect(details[1].keys[1]).toBe(3);\r
432 });\r
433\r
434 it("should return 0 if no item was found", function(){\r
435 expect(collection.remove({ id: 0 })).toBe(0);\r
436 });\r
437\r
438 it("should fire the remove event", function() {\r
439 var source, details;\r
440\r
441 collection.on('remove', function (sender, remove) {\r
442 source = sender;\r
443 details = remove;\r
444 });\r
445\r
446 collection.remove(item1);\r
447\r
448 expect(source).toBe(collection);\r
449 expect(details.at).toBe(0);\r
450 expect(details.items.length).toBe(1);\r
451 expect(details.items[0]).toBe(item1);\r
452 });\r
453 \r
454 it("should only fire a single event if the items are in a large contiguous range", function() {\r
455 var spy = jasmine.createSpy(),\r
456 items = [],\r
457 i;\r
458 \r
459 for (i = 0; i < 1000; ++i) {\r
460 items.push({\r
461 id: i + 1\r
462 });\r
463 }\r
464 collection.add(items);\r
465 collection.on('remove', spy);\r
466 collection.remove(collection.getRange());\r
467 expect(spy.callCount).toBe(1);\r
468 });\r
469 });\r
470 \r
471 describe("removeAt", function() {\r
472 it("should remove a single item", function() {\r
473 collection.removeAt(1);\r
474\r
475 expect(collection.getCount()).toBe(8);\r
476 });\r
477 \r
478 it("should return the removed item", function(){\r
479 expect(collection.removeAt(1)).toBe(item2);\r
480 });\r
481 \r
482 it("should return false if no item was found", function(){\r
483 expect(collection.removeAt(9)).toBeFalsy();\r
484 });\r
485\r
486 describe("event", function() {\r
487 it("should fire the remove event", function() {\r
488 var source, details;\r
489\r
490 collection.on('remove', function (sender, remove) {\r
491 source = sender;\r
492 details = remove;\r
493 });\r
494\r
495 collection.removeAt(1);\r
496\r
497 expect(source).toBe(collection);\r
498 expect(details.at).toBe(1);\r
499 expect(details.items.length).toBe(1);\r
500 expect(details.items[0]).toBe(item2);\r
501 expect(details.keys.length).toBe(1);\r
502 expect(details.keys[0]).toBe(2);\r
503 });\r
504 \r
505 it("should update the collection during a remove", function(){\r
506 var count, item;\r
507 collection.on('remove', function(){\r
508 count = collection.getCount();\r
509 item = collection.getByKey(1);\r
510 });\r
511 collection.removeAt(0);\r
512 expect(count).toBe(8);\r
513 expect(item).toBeUndefined();\r
514 });\r
515 });\r
516\r
517 describe("when filtered", function() {\r
518 it("should remove the correct item with an all inclusive filter", function() {\r
519 collection.getFilters().add(function() {\r
520 return true;\r
521 });\r
522 collection.removeAt(1);\r
523 expect(collection.getAt(0)).toBe(item1);\r
524 expect(collection.getAt(1)).toBe(item3);\r
525 expect(collection.getCount()).toBe(8);\r
526 });\r
527 });\r
528 });\r
529 \r
530 describe("bulkRemove", function(){\r
531 it("should limit the length to that of the collection", function () {\r
532 collection.removeAt(4, 100);\r
533 expect(collection.getCount()).toBe(4);\r
534 });\r
535 \r
536 it("should remove the correct items", function(){\r
537 collection.removeAt(3, 2);\r
538 expect(collection.getCount()).toBe(7);\r
539 expect(collection.getAt(2)).toBe(item3);\r
540 expect(collection.getAt(3)).toBe(item6);\r
541 }); \r
542 });\r
543 \r
544 describe("removeByKey", function() {\r
545 it("should remove a single item", function() {\r
546 collection.removeByKey(1);\r
547\r
548 expect(collection.getCount()).toBe(8);\r
549 });\r
550 \r
551 it("should return the removed item", function(){\r
552 expect(collection.removeByKey(1)).toBe(item1);\r
553 });\r
554 \r
555 it("should return false if no item was found", function(){\r
556 expect(collection.removeByKey(10)).toBeFalsy();\r
557 });\r
558\r
559 it("should fire the remove event", function() {\r
560 var source, details;\r
561\r
562 collection.on('remove', function (sender, remove) {\r
563 source = sender;\r
564 details = remove;\r
565 });\r
566\r
567 collection.removeByKey(2);\r
568\r
569 expect(source).toBe(collection);\r
570 expect(details.at).toBe(1);\r
571 expect(details.items.length).toBe(1);\r
572 expect(details.items[0]).toBe(item2);\r
573 expect(details.keys.length).toBe(1);\r
574 expect(details.keys[0]).toBe(2);\r
575 });\r
576 });\r
577 \r
578 describe("removeAll", function(){\r
579 it("should remove all items", function(){\r
580 collection.removeAll(); \r
581 expect(collection.getCount()).toBe(0); \r
582 });\r
583 \r
584 it("should fire the remove event with no passed items", function(){\r
585 var called = 0,\r
586 source, details;\r
587\r
588 collection.on('remove', function (sender, remove) {\r
589 source = sender;\r
590 details = remove;\r
591 ++called;\r
592 });\r
593\r
594 collection.removeAll();\r
595\r
596 expect(called).toBe(1);\r
597 expect(source).toBe(collection);\r
598 expect(details.at).toBe(0);\r
599 expect(details.items.length).toBe(9);\r
600 expect(details.items).toEqual([item1, item2, item3, item4, item5, item6,\r
601 item7, item8, item9]);\r
602 expect(details.keys.length).toBe(9);\r
603 expect(details.keys).toEqual([1,2,3,4,5,6,7,8,9]);\r
604 });\r
605 });\r
606 });\r
607\r
608 describe("clearing items", function() {\r
609 beforeEach(function() {\r
610 collection = new Ext.util.Collection();\r
611\r
612 collection.add([{id: 1}, {id: 2}]);\r
613 });\r
614\r
615 it("should remove all items", function() {\r
616 expect(collection.length).toBe(2);\r
617\r
618 collection.clear();\r
619\r
620 expect(collection.length).toBe(0);\r
621 });\r
622\r
623 it("should not fire the remove event", function() {\r
624 var called = 0;\r
625\r
626 collection.on('remove', function() {\r
627 ++called;\r
628 });\r
629\r
630 collection.clear();\r
631\r
632 expect(called).toBe(0);\r
633 });\r
634 });\r
635\r
636 describe("determining insertion index in a sorted Collection", function() {\r
637\r
638 // Items to sort into name order\r
639 var item1 = {id: 2, name: 'Michael'},\r
640 item2 = {id: 3, name: 'Yanto'},\r
641 item3 = {id: 1, name: 'Bill'},\r
642\r
643 // Items to find insertion indices for\r
644 item4 = {id: 4, name: 'Albert'}, // Insert index 0 when ASC, 3 when DESC\r
645 item5 = {id: 5, name: 'Fred'}, // Insert index 1 when ASC, 2 when DESC\r
646 item6 = {id: 6, name: 'Robert'}, // Insert index 2 when ASC, 1 when DESC\r
647 item7 = {id: 7, name: 'Zebedee'};// Insert index 3 when ASC, 0 when DESC\r
648\r
649 beforeEach(function() {\r
650 collection = new Ext.util.Collection();\r
651 collection.add([item1, item2, item3]);\r
652 });\r
653\r
654 function getInsertIndex (item) {\r
655 collection.add(item);\r
656 var ret = collection.indexOf(item);\r
657 collection.remove(item);\r
658 return ret;\r
659 }\r
660\r
661 describe("Sorted ascending", function() {\r
662 it("should find correct insertion indices", function() {\r
663 collection.sort('name');\r
664\r
665 expect(getInsertIndex(item4)).toBe(0);\r
666 expect(getInsertIndex(item5)).toBe(1);\r
667 expect(getInsertIndex(item6)).toBe(2);\r
668 expect(getInsertIndex(item7)).toBe(3);\r
669 });\r
670 });\r
671\r
672 describe("Sorted descending", function() {\r
673 it("should find correct insertion indices", function() {\r
674 collection.sort('name', 'DESC');\r
675\r
676 expect(getInsertIndex(item4)).toBe(3);\r
677 expect(getInsertIndex(item5)).toBe(2);\r
678 expect(getInsertIndex(item6)).toBe(1);\r
679 expect(getInsertIndex(item7)).toBe(0);\r
680 });\r
681 });\r
682 });\r
683\r
684 describe("an existing Collection", function() {\r
685 var item1 = {id: 1, name: 'first'},\r
686 item2 = {id: 2, name: 'second'},\r
687 item3 = {id: 3, name: 'third'},\r
688 item4 = {id: 4, name: 'fourth'},\r
689 item5 = {id: 5, name: 'fifth'},\r
690 item6 = {id: 6, name: 'sixth'},\r
691 item7 = {id: 7, name: 'seventh'},\r
692 item8 = {id: 8, name: 'eighth'},\r
693 item9 = {id: 9, name: 'ninth'};\r
694 \r
695 function fill () {\r
696 collection.clear();\r
697 collection.add([\r
698 item1, // 0 -9\r
699 item2, // 1 -8\r
700 item3, // 2 -7\r
701 item4, // 3 -6\r
702 item5, // 4 -5\r
703 item6, // 5 -4\r
704 item7, // 6 -3\r
705 item8, // 7 -2\r
706 item9 // 8 -1\r
707 ]);\r
708 };\r
709\r
710 var generation;\r
711\r
712 beforeEach(function() {\r
713 collection = new Ext.util.Collection();\r
714\r
715 collection.add([item1, item2, item3]);\r
716 generation = collection.generation;\r
717 });\r
718 \r
719 describe("updateKey", function(){\r
720 it("should do nothing if the old key doesn't exist for member item", function() {\r
721 collection.updateKey(item1, 'bar');\r
722 expect(collection.getByKey('bar')).toBeUndefined();\r
723 expect(collection.getByKey(item1.id)).toBe(item1);\r
724\r
725 expect(collection.generation).toBe(generation); // no changes made\r
726 });\r
727\r
728 it("should do nothing if the old key doesn't exist for non-member item", function() {\r
729 collection.updateKey(item4, 'bar');\r
730 expect(collection.getByKey('bar')).toBeUndefined();\r
731 expect(collection.getByKey(item4.id)).toBe(undefined);\r
732\r
733 expect(collection.generation).toBe(generation); // no changes made\r
734 });\r
735\r
736 it("should throw if old key is a different item", function() {\r
737 expect(function () {\r
738 collection.updateKey(item4, item1.id);\r
739 }).toThrow();\r
740\r
741 expect(collection.getByKey(item4.id)).toBe(undefined);\r
742\r
743 expect(collection.generation).toBe(generation); // no changes made\r
744 });\r
745\r
746 it("should throw if new key collides with a different item", function() {\r
747 // Replace item1 so we can change its key and not have any issues with\r
748 // an error for claiming newItem1 was the item by id=1. We just want to\r
749 // check for the collision on the new id.\r
750 var newItem1 = Ext.apply({}, item1);\r
751 collection.add(newItem1);\r
752\r
753 generation = collection.generation;\r
754\r
755 newItem1.id = item3.id;\r
756\r
757 expect(function () {\r
758 collection.updateKey(newItem1, item1.id);\r
759 }).toThrow();\r
760\r
761 expect(collection.getByKey(item3.id)).toBe(item3);\r
762\r
763 expect(collection.generation).toBe(generation); // no changes made\r
764 });\r
765\r
766 it("should update the key for the item", function () {\r
767 var newItem1 = Ext.apply({}, item1);\r
768\r
769 collection.clear();\r
770 collection.add(newItem1, item2, item3);\r
771\r
772 newItem1.id = 20;\r
773\r
774 collection.updateKey(newItem1, 1);\r
775\r
776 expect(collection.getByKey(1)).toBeUndefined();\r
777 expect(collection.getByKey(20)).toBe(newItem1);\r
778\r
779 // The index must no longer contain the old key\r
780 expect(collection.indexOfKey(1)).toBe(-1);\r
781 expect(collection.indexOfKey(20)).toBe(0);\r
782 });\r
783 });\r
784\r
785 describe("inserting items", function() {\r
786 it("should insert a new item", function() {\r
787 var count = collection.getCount();\r
788\r
789 collection.insert(0, item4);\r
790\r
791 expect(collection.getCount()).toBe(count + 1);\r
792 });\r
793\r
794 it("should fire the add event", function() {\r
795 var called = 0,\r
796 source, details;\r
797\r
798 collection.on('add', function (sender, add) {\r
799 ++called;\r
800 source = sender;\r
801 details = add;\r
802 });\r
803\r
804 collection.insert(0, item4);\r
805\r
806 expect(called).toBe(1);\r
807 expect(source).toBe(collection);\r
808 expect(details.at).toBe(0);\r
809 expect(details.items.length).toBe(1);\r
810 expect(details.items[0]).toBe(item4);\r
811 expect(details.keys.length).toBe(1);\r
812 expect(details.keys[0]).toBe(4);\r
813 });\r
814\r
815 it("should insert the item at the correct location", function() {\r
816 expect(collection.items[0]).toBe(item1);\r
817\r
818 collection.insert(0, item4);\r
819\r
820 expect(collection.items[0]).toBe(item4);\r
821 });\r
822\r
823 describe("with a source", function() {\r
824 var child, newItem;\r
825\r
826 beforeEach(function() {\r
827 fill();\r
828 child = new Ext.util.Collection();\r
829 child.setSource(collection);\r
830\r
831 newItem = {\r
832 id: 100,\r
833 name: 'Foo'\r
834 };\r
835 });\r
836\r
837 afterEach(function() {\r
838 child.destroy();\r
839 newItem = child = null;\r
840 });\r
841\r
842 describe("inserting into the source", function() {\r
843 it("should have the correct position when inserting at the start", function() {\r
844 collection.insert(0, newItem);\r
845 expect(child.getAt(0)).toBe(newItem);\r
846 });\r
847\r
848 it("should have the correct position when inserting into the middle", function() {\r
849 collection.insert(4, newItem);\r
850 expect(child.getAt(4)).toBe(newItem);\r
851 });\r
852\r
853 it("should have the correct position when inserting at the end", function() {\r
854 collection.insert(100, newItem);\r
855 expect(collection.getAt(9)).toBe(newItem);\r
856 });\r
857\r
858 describe("with source sorted", function() {\r
859 it("should take the sorted position from the source", function() {\r
860 collection.getSorters().add(function(item1, item2) {\r
861 var n1 = item1.name,\r
862 n2 = item2.name;\r
863\r
864 if (n1 === n2) {\r
865 return 0;\r
866 }\r
867 return n1 < n2 ? -1 : 1;\r
868 });\r
869 newItem.name = 'a';\r
870 collection.insert(100, newItem);\r
871 expect(child.getAt(0)).toBe(newItem);\r
872 });\r
873 });\r
874\r
875 describe("with the child filtered", function() {\r
876 it("hould have the correct position when inserting at the start", function() {\r
877 child.getFilters().add(function(item) {\r
878 return item.name === 'third' || item.name === 'seventh' || item.name === 'Foo';\r
879 });\r
880 collection.insert(0, newItem);\r
881 expect(child.getAt(0)).toBe(newItem);\r
882 });\r
883\r
884 it("should have the correct position when inserting into the middle", function() {\r
885 child.getFilters().add(function(item) {\r
886 return item.name === 'third' || item.name === 'seventh' || item.name === 'Foo';\r
887 });\r
888 collection.insert(5, newItem);\r
889 expect(child.getAt(1)).toBe(newItem);\r
890 });\r
891\r
892 it("should have the correct position when inserting at the end", function() {\r
893 child.getFilters().add(function(item) {\r
894 return item.name === 'third' || item.name === 'seventh' || item.name === 'Foo';\r
895 });\r
896 collection.insert(100, newItem);\r
897 expect(child.getAt(2)).toBe(newItem);\r
898 });\r
899\r
900 it("should have the correct position when the nearest item in the child is the first item in the source", function() {\r
901 child.getFilters().add(function(item) {\r
902 return item.name === 'first' || item.name === 'seventh' || item.name === 'Foo';\r
903 });\r
904 collection.insert(3, newItem);\r
905 expect(child.getAt(1)).toBe(newItem);\r
906 });\r
907\r
908 it("should have the correct position when there is no nearest item in the source", function() {\r
909 child.getFilters().add(function(item) {\r
910 return item.name === 'seventh' || item.name === 'Foo';\r
911 });\r
912 collection.insert(3, newItem);\r
913 expect(child.getAt(0)).toBe(newItem);\r
914 });\r
915 });\r
916 });\r
917\r
918 describe("inserting into the child", function() {\r
919 it("should have the correct position when inserting at the start", function() {\r
920 child.insert(0, newItem);\r
921 expect(collection.getAt(0)).toBe(newItem);\r
922 });\r
923\r
924 it("should have the correct position when inserting into the middle", function() {\r
925 child.insert(4, newItem);\r
926 expect(collection.getAt(4)).toBe(newItem);\r
927 });\r
928\r
929 it("should have the correct position when inserting at the end", function() {\r
930 child.insert(100, newItem);\r
931 expect(collection.getAt(9)).toBe(newItem);\r
932 });\r
933\r
934 describe("with the source sorted", function() {\r
935 it("should use the specified position", function() {\r
936 collection.sort('name');\r
937 var item = {id: 100, name: 'zzzz'};\r
938 child.insert(0, item);\r
939 expect(child.getAt(0)).toBe(item);\r
940 expect(collection.getAt(9)).toBe(item);\r
941 });\r
942 });\r
943\r
944 describe("when filtered", function() {\r
945 it("should adjust the position for the source collection", function() {\r
946 child.getFilters().add(function(item) {\r
947 return item.name !== 'first' && item.name !== 'second';\r
948 });\r
949 child.insert(0, newItem);\r
950 expect(collection.indexOf(newItem)).toBe(2);\r
951 });\r
952 });\r
953 });\r
954\r
955 it("should not cause an exception when modifying the item in the source onCollectionAdd & the child is sorted", function() {\r
956 var o = {\r
957 observerPriority: -1000,\r
958 onCollectionAdd: function(source, details) {\r
959 var item = details.items[0];\r
960 item.name = 'asdf';\r
961 expect(function() {\r
962 collection.itemChanged(item, ['name']);\r
963 }).not.toThrow();\r
964 }\r
965 };\r
966\r
967 child.getSorters().add('name');\r
968\r
969 collection.addObserver(o);\r
970\r
971 collection.add({\r
972 id: 1000,\r
973 name: 'q'\r
974 });\r
975 });\r
976 });\r
977 });\r
978\r
979 describe("replacing items", function() {\r
980 it("should replace the correct item", function() {\r
981 collection.splice(1, 1, [item4]);\r
982\r
983 expect(collection.getAt(1)).toBe(item4);\r
984 });\r
985\r
986 it("should not change the count", function() {\r
987 var count = collection.getCount();\r
988\r
989 collection.splice(1, 1, [item4]);\r
990\r
991 expect(collection.getCount()).toBe(count);\r
992 });\r
993\r
994 it("should fire the proper events", function() {\r
995 var log = [];\r
996\r
997 logEvents(collection, log, 'name');\r
998\r
999 collection.splice(1, 1, [item4]);\r
1000\r
1001 expect(log).toEqual([\r
1002 'beginupdate',\r
1003 'remove ["second"] at 1 w/keys [2]',\r
1004 'add ["fourth"] at 1 w/keys [4]',\r
1005 'endupdate'\r
1006 ]);\r
1007 });\r
1008 });\r
1009\r
1010 describe("cloning", function() {\r
1011 it("should copy all items into the new Collection", function() {\r
1012 var mc2 = collection.clone();\r
1013\r
1014 expect(mc2.getCount()).toBe(3);\r
1015 expect(mc2.items[0]).toBe(item1);\r
1016 expect(mc2.items[1]).toBe(item2);\r
1017 expect(mc2.items[2]).toBe(item3);\r
1018 });\r
1019 \r
1020 it("should keep the getKey fn", function(){\r
1021 var fn = function(o){\r
1022 return o.id; \r
1023 }, mc1 = new Ext.util.Collection({\r
1024 keyFn: fn\r
1025 });\r
1026 \r
1027 var mc2 = mc1.clone();\r
1028 expect(mc2.getKey).toBe(fn);\r
1029 mc1 = mc2 = null;\r
1030 });\r
1031 });\r
1032\r
1033 describe("getting items", function() {\r
1034 \r
1035 it("should get an item's key", function() {\r
1036 expect(collection.getKey(item1)).toBe(1);\r
1037 });\r
1038 \r
1039 describe("first", function() {\r
1040 it("should get the first item", function() {\r
1041 expect(collection.first()).toBe(item1);\r
1042 });\r
1043 \r
1044 it("should return undefined if the collection is empty", function() {\r
1045 collection = new Ext.util.Collection();\r
1046 expect(collection.first()).toBeUndefined();\r
1047 });\r
1048 });\r
1049 \r
1050 describe("last", function() {\r
1051 it("should get the last item", function() {\r
1052 expect(collection.last()).toBe(item3);\r
1053 });\r
1054 \r
1055 it("should return undefined if the collection is empty", function() {\r
1056 collection = new Ext.util.Collection();\r
1057 expect(collection.last()).toBeUndefined();\r
1058 });\r
1059 });\r
1060 \r
1061 describe("get", function() {\r
1062 it("should get by key", function() {\r
1063 expect(collection.get(2)).toBe(item2);\r
1064 });\r
1065 \r
1066 it("should return undefined if the key doesn't exist", function() {\r
1067 expect(collection.get(100)).toBeUndefined();\r
1068 });\r
1069 \r
1070 it("should get an newly added item", function() {\r
1071 var item5 = {id: 'a', name: 'fifth item'};\r
1072 collection.add(item5);\r
1073 expect(collection.get('a')).toBe(item5);\r
1074 });\r
1075 });\r
1076\r
1077 describe("indexOf", function() {\r
1078 it("should return the correct indexOf an item", function() {\r
1079 expect(collection.indexOf(item1)).toBe(0);\r
1080 });\r
1081 \r
1082 it("should return -1 if the item does not exist in the collection", function() {\r
1083 expect(collection.indexOf({id: 73})).toBe(-1);\r
1084 });\r
1085 \r
1086 it("should handle null", function() {\r
1087 expect(collection.indexOf(null)).toBe(-1);\r
1088 });\r
1089 });\r
1090 \r
1091 describe("indexOfKey", function() {\r
1092 it("should return the correct indexOfKey", function() {\r
1093 expect(collection.indexOfKey(2)).toBe(1);\r
1094 });\r
1095 \r
1096 it("should return -1 if the key does not exist", function() {\r
1097 expect(collection.indexOfKey(42)).toBe(-1);\r
1098 });\r
1099 });\r
1100 \r
1101 describe("get by key", function() {\r
1102 it("should return the correct key", function() {\r
1103 expect(collection.getByKey(3)).toBe(item3);\r
1104 });\r
1105 \r
1106 it("should return undefined if the key does not exist", function() {\r
1107 expect(collection.getByKey(1200)).toBeUndefined();\r
1108 });\r
1109 });\r
1110 \r
1111 describe("getAt", function() {\r
1112 it("should get an item by index", function() {\r
1113 expect(collection.getAt(2)).toBe(item3);\r
1114 });\r
1115 \r
1116 it("should return undefined if the index is out of bounds", function() {\r
1117 expect(collection.getAt(33)).toBeUndefined();\r
1118 });\r
1119 });\r
1120\r
1121 describe("when getting a range", function() {\r
1122 it("should honor the start and limit params", function() {\r
1123 fill();\r
1124 var items = collection.getRange(1, 3);\r
1125\r
1126 expect(items.length).toBe(2);\r
1127 expect(items[0]).toBe(item2);\r
1128 expect(items[1]).toBe(item3);\r
1129 });\r
1130\r
1131 it("should return all items if no params are given", function() {\r
1132 fill();\r
1133 var items = collection.getRange();\r
1134\r
1135 expect(items.length).toBe(9);\r
1136 expect(items[0]).toBe(item1);\r
1137 expect(items[1]).toBe(item2);\r
1138 expect(items[2]).toBe(item3);\r
1139 expect(items[8]).toBe(item9);\r
1140 });\r
1141\r
1142 it("should return all items to the end if only the start param is given", function() {\r
1143 fill();\r
1144 var items = collection.getRange(1);\r
1145\r
1146 expect(items.length).toBe(8);\r
1147 expect(items[0]).toBe(item2);\r
1148 expect(items[1]).toBe(item3);\r
1149 expect(items[7]).toBe(item9);\r
1150 });\r
1151 \r
1152 it("should wrap the start value if negative", function(){\r
1153 fill();\r
1154 var items = collection.getRange(-6, 6);\r
1155 expect(items.length).toBe(3);\r
1156 expect(items[0]).toBe(item4);\r
1157 expect(items[1]).toBe(item5);\r
1158 expect(items[2]).toBe(item6);\r
1159 });\r
1160 \r
1161 it("should normalize the end value the collection max", function(){\r
1162 fill();\r
1163 var items = collection.getRange(6, 200);\r
1164 expect(items.length).toBe(3);\r
1165 expect(items[0]).toBe(item7);\r
1166 });\r
1167 \r
1168 it("should return empty if start > length", function(){\r
1169 fill();\r
1170 var items = collection.getRange(10, 15);\r
1171 expect(items.length).toBe(0);\r
1172 });\r
1173 });\r
1174 });\r
1175\r
1176 describe("finding items", function() {\r
1177 describe("findBy", function() {\r
1178 beforeEach(function() {\r
1179 fill();\r
1180 });\r
1181 \r
1182 it("should find an item using a passed function", function() {\r
1183 var matched = collection.findBy(function(item) {\r
1184 return item.name === 'third';\r
1185 });\r
1186\r
1187 expect(matched).toBe(item3);\r
1188 });\r
1189 \r
1190 it("should stop iterating once a match is found", function() {\r
1191 var count = 0;\r
1192 collection.findBy(function(item) {\r
1193 ++count;\r
1194 return item.name === 'third';\r
1195 });\r
1196\r
1197 expect(count).toBe(3);\r
1198 });\r
1199 \r
1200 it("should return null if the item is not matched", function() {\r
1201 var matched = collection.findBy(function(item) {\r
1202 return false;\r
1203 });\r
1204 expect(matched).toBeNull();\r
1205 });\r
1206 \r
1207 it("should pass the item and the key", function() {\r
1208 var spy = jasmine.createSpy().andReturn(true);\r
1209 collection.findBy(spy);\r
1210 expect(spy).toHaveBeenCalledWith(item1, 1);\r
1211 });\r
1212 \r
1213 describe("scope", function() {\r
1214 it("should default the scope to the collection", function() {\r
1215 var scope;\r
1216 collection.findBy(function() {\r
1217 scope = this;\r
1218 return true;\r
1219 });\r
1220 expect(scope).toBe(collection);\r
1221 });\r
1222 \r
1223 it("should use the passed scope", function() {\r
1224 var scope;\r
1225 collection.findBy(function() {\r
1226 scope = this;\r
1227 return true;\r
1228 }, fakeScope);\r
1229 expect(scope).toBe(fakeScope);\r
1230 });\r
1231 });\r
1232 \r
1233 describe("start", function() {\r
1234 it("should not iterate at all if start > length", function() {\r
1235 var count = 0;\r
1236 collection.findBy(function() {\r
1237 ++count;\r
1238 }, null, 1000);\r
1239 expect(count).toBe(0);\r
1240 });\r
1241 \r
1242 it("should start from the passed index", function() {\r
1243 var keys = [];\r
1244 collection.findBy(function(item, key) {\r
1245 keys.push(key);\r
1246 }, null, 4);\r
1247 expect(keys.join(',')).toBe('5,6,7,8,9');\r
1248 });\r
1249 \r
1250 it("should not wrap around", function() {\r
1251 var matched = collection.findBy(function(item) {\r
1252 return item.name === 'second';\r
1253 }, null, 6);\r
1254 expect(matched).toBeNull();\r
1255 });\r
1256 \r
1257 it("should find an item after the start", function() {\r
1258 var matched = collection.findBy(function(item) {\r
1259 return item.name === 'third' || item.name === 'ninth';\r
1260 }, null, 5);\r
1261 expect(matched).toBe(item9);\r
1262 });\r
1263 });\r
1264 });\r
1265 \r
1266 describe("findIndexBy", function() {\r
1267 beforeEach(function() {\r
1268 fill();\r
1269 });\r
1270 \r
1271 it("should find an item using a passed function", function() {\r
1272 var index = collection.findIndexBy(function(item) {\r
1273 return item.name === 'third';\r
1274 });\r
1275\r
1276 expect(index).toBe(2);\r
1277 });\r
1278 \r
1279 it("should stop iterating once a match is found", function() {\r
1280 var count = 0;\r
1281 collection.findIndexBy(function(item) {\r
1282 ++count;\r
1283 return item.name === 'third';\r
1284 });\r
1285\r
1286 expect(count).toBe(3);\r
1287 });\r
1288 \r
1289 it("should return -1 if the item is not matched", function() {\r
1290 var index = collection.findIndexBy(function(item) {\r
1291 return false;\r
1292 });\r
1293 expect(index).toBe(-1);\r
1294 });\r
1295 \r
1296 it("should pass the item and the key", function() {\r
1297 var spy = jasmine.createSpy().andReturn(true);\r
1298 collection.findIndexBy(spy);\r
1299 expect(spy).toHaveBeenCalledWith(item1, 1);\r
1300 });\r
1301 \r
1302 describe("scope", function() {\r
1303 it("should default the scope to the collection", function() {\r
1304 var scope;\r
1305 collection.findIndexBy(function() {\r
1306 scope = this;\r
1307 return true;\r
1308 });\r
1309 expect(scope).toBe(collection);\r
1310 });\r
1311 \r
1312 it("should use the passed scope", function() {\r
1313 var scope;\r
1314 collection.findIndexBy(function() {\r
1315 scope = this;\r
1316 return true;\r
1317 }, fakeScope);\r
1318 expect(scope).toBe(fakeScope);\r
1319 });\r
1320 });\r
1321 \r
1322 describe("start", function() {\r
1323 it("should not iterate at all if start > length", function() {\r
1324 var count = 0;\r
1325 collection.findIndexBy(function() {\r
1326 ++count;\r
1327 }, null, 1000);\r
1328 expect(count).toBe(0);\r
1329 });\r
1330 \r
1331 it("should start from the passed index", function() {\r
1332 var keys = [];\r
1333 collection.findIndexBy(function(item, key) {\r
1334 keys.push(key);\r
1335 }, null, 4);\r
1336 expect(keys.join(',')).toBe('5,6,7,8,9');\r
1337 });\r
1338 \r
1339 it("should not wrap around", function() {\r
1340 var index = collection.findIndexBy(function(item) {\r
1341 return item.name === 'second';\r
1342 }, null, 6);\r
1343 expect(index).toBe(-1);\r
1344 });\r
1345 \r
1346 it("should find an item after the start", function() {\r
1347 var index = collection.findIndexBy(function(item) {\r
1348 return item.name === 'third' || item.name === 'ninth';\r
1349 }, null, 5);\r
1350 expect(index).toBe(8);\r
1351 });\r
1352 });\r
1353 });\r
1354\r
1355 describe("findIndex", function() {\r
1356 beforeEach(function() {\r
1357 fill();\r
1358 });\r
1359 \r
1360 it("should find an item's index", function() {\r
1361 var index = collection.findIndex('name', 'third');\r
1362 expect(index).toBe(2);\r
1363 });\r
1364 \r
1365 it("should return -1 if there is no match", function() {\r
1366 var index = collection.findIndex('name', 'foo');\r
1367 expect(index).toBe(-1);\r
1368 });\r
1369 \r
1370 it("should respect the root property", function() {\r
1371 collection = new Ext.util.Collection({\r
1372 rootProperty: 'root'\r
1373 });\r
1374 collection.add({\r
1375 id: 1,\r
1376 root: {\r
1377 name: 'A'\r
1378 }\r
1379 }, {\r
1380 id: 2,\r
1381 root: {\r
1382 name: 'B'\r
1383 }\r
1384 }, {\r
1385 id: 3,\r
1386 root: {\r
1387 name: 'C'\r
1388 }\r
1389 });\r
1390 var index = collection.findIndex('name', 'B');\r
1391 expect(index).toBe(1);\r
1392 });\r
1393 \r
1394 describe("options", function() {\r
1395 describe("startIndex", function() {\r
1396 it("should match from the startIndex, including the start", function() {\r
1397 var index = collection.findIndex('name', 's', 6, null, false);\r
1398 expect(index).toBe(6);\r
1399 });\r
1400 \r
1401 it("should find items after the startIndex", function() {\r
1402 var index = collection.findIndex('name', 's', 4, null, false);\r
1403 expect(index).toBe(5);\r
1404 });\r
1405 \r
1406 it("should return -1 if the startIndex is larger than the length", function() {\r
1407 var index = collection.findIndex('name', 's', 100);\r
1408 expect(index).toBe(-1);\r
1409 });\r
1410 \r
1411 it("should not 'wrap' over the collection", function() {\r
1412 var index = collection.findIndex('name', 'one', 2);\r
1413 expect(index).toBe(-1);\r
1414 });\r
1415 });\r
1416 \r
1417 describe("regex options", function() {\r
1418 describe("startsWith/endsWith", function() {\r
1419 it("should default startsWith & endsWith to true", function() {\r
1420 var index = collection.findIndex('name', 'second');\r
1421 expect(index).toBe(1);\r
1422 index = collection.findIndex('name', 'secon');\r
1423 expect(index).toBe(-1);\r
1424 index = collection.findIndex('name', 'econd');\r
1425 expect(index).toBe(-1);\r
1426 });\r
1427 \r
1428 it("should match the start of the string when passing endsWith: false", function() {\r
1429 var index = collection.findIndex('name', 'second', null, null, false);\r
1430 expect(index).toBe(1);\r
1431 index = collection.findIndex('name', 'secon', null, null, false);\r
1432 expect(index).toBe(1);\r
1433 index = collection.findIndex('name', 'econd', null, null, false);\r
1434 expect(index).toBe(-1);\r
1435 });\r
1436 \r
1437 it("should match the end of the string when passing startsWith: false", function() {\r
1438 var index = collection.findIndex('name', 'second', null, false);\r
1439 expect(index).toBe(1);\r
1440 index = collection.findIndex('name', 'econd', null, false);\r
1441 expect(index).toBe(1);\r
1442 index = collection.findIndex('name', 'secon', null, false);\r
1443 expect(index).toBe(-1);\r
1444 });\r
1445 \r
1446 it("should match anywhere in the string when using startsWith/endsWith false", function() {\r
1447 var index = collection.findIndex('name', 'con', null, false, false);\r
1448 expect(index).toBe(1);\r
1449 });\r
1450 });\r
1451 \r
1452 describe("case", function() {\r
1453 it("should be case insensitive by default", function() {\r
1454 var index = collection.findIndex('name', 'SEVENTH');\r
1455 expect(index).toBe(6);\r
1456 });\r
1457 \r
1458 it("should respect case when passing the ignoreCase flag", function() {\r
1459 var index = collection.findIndex('name', 'SEVENTH', null, null, null, false);\r
1460 expect(index).toBe(-1);\r
1461 });\r
1462 });\r
1463 });\r
1464 });\r
1465 });\r
1466 });\r
1467\r
1468 describe("contains", function() {\r
1469 it("should contain items that have been added", function() {\r
1470 expect(collection.contains(item1)).toBe(true);\r
1471 });\r
1472\r
1473 it("should not contain items that have not been added", function() {\r
1474 expect(collection.contains({ id: 0 })).toBe(false);\r
1475 });\r
1476\r
1477 it("should contain an item by key", function() {\r
1478 expect(collection.containsKey(1)).toBe(true);\r
1479 });\r
1480\r
1481 it("should not contain a non-contained item by key", function() {\r
1482 expect(collection.containsKey(100)).toBe(false);\r
1483 });\r
1484 });\r
1485 });\r
1486\r
1487 describe("createFiltered", function() {\r
1488 var filter, filtered;\r
1489\r
1490 beforeEach(function() {\r
1491 collection = new Ext.util.Collection({\r
1492 keyFn: function(item) {\r
1493 return item.name;\r
1494 }\r
1495 });\r
1496\r
1497 collection.add([\r
1498 {id: 1, name: 'Ed', code: 'C', modifier: 10},\r
1499 {id: 2, name: 'Abe', code: 'A', modifier: 100},\r
1500 {id: 3, name: 'Edward', code: 'B', modifier: 5}\r
1501 ]);\r
1502\r
1503 filter = new Ext.util.Filter({\r
1504 filterFn: function(item) {\r
1505 return item.name.charAt(0) === 'E';\r
1506 }\r
1507 });\r
1508 });\r
1509 \r
1510 describe("copying", function() {\r
1511 it("should return a new Collection", function() {\r
1512 filtered = collection.createFiltered('name', 'Ed');\r
1513\r
1514 expect(filtered instanceof Ext.util.Collection).toBe(true);\r
1515 expect(filtered).not.toBe(collection);\r
1516 });\r
1517 \r
1518 it("should keep the getKey function when using filter", function(){\r
1519 var fn = function(o){\r
1520 return o.id; \r
1521 }, mc1 = new Ext.util.Collection({\r
1522 keyFn: fn\r
1523 });\r
1524\r
1525 var mc2 = mc1.createFiltered('name', 'Ed');\r
1526 expect(mc2.getKey).toBe(fn);\r
1527 mc1 = mc2 = null;\r
1528 });\r
1529 \r
1530 it("should keep the getKey function when using filterBy", function(){\r
1531 var fn = function(o){\r
1532 return o.id; \r
1533 }, mc1 = new Ext.util.Collection({\r
1534 keyFn: fn\r
1535 });\r
1536\r
1537 var mc2 = mc1.createFiltered(function(){\r
1538 return true;\r
1539 });\r
1540 expect(mc2.getKey).toBe(fn);\r
1541 mc1 = mc2 = null;\r
1542 });\r
1543 });\r
1544\r
1545 describe("when filtering on a key and value pair", function() {\r
1546 it("should filter correctly", function() {\r
1547 filtered = collection.createFiltered('name', 'Edward');\r
1548\r
1549 expect(filtered.items[0].name).toBe('Edward');\r
1550 expect(filtered.length).toBe(1); \r
1551 });\r
1552\r
1553 it("should use anyMatch by default", function () {\r
1554 filtered = collection.createFiltered('name', 'Ed');\r
1555\r
1556 expect(filtered.length).toBe(2);\r
1557 });\r
1558 \r
1559 it("should respect the root property", function() {\r
1560 collection = new Ext.util.Collection({\r
1561 rootProperty: 'root'\r
1562 });\r
1563 collection.add({\r
1564 id: 1,\r
1565 root: {\r
1566 name: 'A'\r
1567 }\r
1568 }, {\r
1569 id: 2,\r
1570 root: {\r
1571 name: 'B'\r
1572 }\r
1573 });\r
1574 filtered = collection.createFiltered('name', 'A');\r
1575 expect(filtered.getCount()).toBe(1);\r
1576 });\r
1577 });\r
1578\r
1579 describe("when filtering using Filter object", function() {\r
1580 it("should accept a single Filter", function() {\r
1581 filtered = collection.createFiltered(filter);\r
1582\r
1583 expect(filtered.length).toBe(2);\r
1584 });\r
1585 \r
1586 it("should respect the root property", function() {\r
1587 collection = new Ext.util.Collection({\r
1588 rootProperty: 'root'\r
1589 });\r
1590 collection.add({\r
1591 id: 1,\r
1592 root: {\r
1593 name: 'A'\r
1594 }\r
1595 }, {\r
1596 id: 2,\r
1597 root: {\r
1598 name: 'B'\r
1599 }\r
1600 });\r
1601 filtered = collection.createFiltered(new Ext.util.Filter({\r
1602 property: 'name',\r
1603 value: 'A'\r
1604 }));\r
1605 expect(filtered.getCount()).toBe(1);\r
1606 });\r
1607 \r
1608 describe("array of filters", function() {\r
1609 it("should accept an array of Filters", function() {\r
1610 filtered = collection.createFiltered([filter]);\r
1611 expect(filtered.length).toBe(2);\r
1612 });\r
1613 \r
1614 it("should respect the root property", function() {\r
1615 collection = new Ext.util.Collection({\r
1616 rootProperty: 'root'\r
1617 });\r
1618 collection.add({\r
1619 id: 1,\r
1620 root: {\r
1621 name: 'A'\r
1622 }\r
1623 }, {\r
1624 id: 2,\r
1625 root: {\r
1626 name: 'B'\r
1627 }\r
1628 });\r
1629 filtered = collection.createFiltered([new Ext.util.Filter({\r
1630 property: 'name',\r
1631 value: 'A'\r
1632 })]);\r
1633 expect(filtered.getCount()).toBe(1);\r
1634 });\r
1635 });\r
1636 });\r
1637 }); // createFiltered\r
1638\r
1639 describe("filters collection management", function() {\r
1640 var item0 = { id: 0, name: 'abba' },\r
1641 item1 = { id: 1, name: 'aaa' },\r
1642 item2 = { id: 2, name: 'bad' },\r
1643 item3 = { id: 3, name: 'ccc' },\r
1644 item4 = { id: 4, name: 'abc' },\r
1645 item5 = { id: 5, name: 'bcd' },\r
1646 item6 = { id: 6, name: 'cde' },\r
1647 item7 = { id: 7, name: 'xyz' },\r
1648 item8 = { id: 8, name: 'ddd' },\r
1649 item9 = { id: 9, name: 'dad' },\r
1650 item10 = { id: 10, name: 'dood'};\r
1651\r
1652 beforeEach(function() {\r
1653 collection = new Ext.util.Collection();\r
1654 collection.add(item1, item2, item3, item4, item5, item6, item7, item8, item9);\r
1655 });\r
1656\r
1657 describe('single filter', function () {\r
1658 it('should save original items on filter and restore on clear', function () {\r
1659 var refreshes = 0,\r
1660 filters = collection.getFilters();\r
1661\r
1662 collection.on('refresh', function () {\r
1663 ++refreshes;\r
1664 });\r
1665\r
1666 expect(collection.length).toBe(9);\r
1667 expect(filters.length).toBe(0);\r
1668 expect(collection.filtered).toBe(false);\r
1669\r
1670 filters.add({ property: 'name', value: 'a' });\r
1671\r
1672 expect(refreshes).toBe(1);\r
1673 expect(filters.length).toBe(1);\r
1674 expect(collection.filtered).toBe(true);\r
1675 expect(collection.length).toBe(2);\r
1676 expect(collection.items[0]).toBe(item1);\r
1677 expect(collection.items[1]).toBe(item4);\r
1678\r
1679 filters.removeAll();\r
1680\r
1681 expect(refreshes).toBe(2);\r
1682 expect(filters.length).toBe(0);\r
1683 expect(collection.filtered).toBe(false);\r
1684 expect(collection.length).toBe(9);\r
1685 expect(collection.items[0]).toBe(item1);\r
1686 expect(collection.items[1]).toBe(item2);\r
1687 expect(collection.items[2]).toBe(item3);\r
1688 expect(collection.items[3]).toBe(item4);\r
1689 expect(collection.items[4]).toBe(item5);\r
1690 expect(collection.items[5]).toBe(item6);\r
1691 expect(collection.items[6]).toBe(item7);\r
1692 expect(collection.items[7]).toBe(item8);\r
1693 expect(collection.items[8]).toBe(item9);\r
1694 });\r
1695\r
1696 it('should add items even when filtered', function () {\r
1697 var refreshes = 0,\r
1698 filters = collection.getFilters();\r
1699\r
1700 collection.on('refresh', function () {\r
1701 ++refreshes;\r
1702 });\r
1703\r
1704 expect(collection.length).toBe(9);\r
1705 expect(filters.length).toBe(0);\r
1706 expect(collection.filtered).toBe(false);\r
1707\r
1708 filters.add({ property: 'name', value: 'a' });\r
1709\r
1710 expect(refreshes).toBe(1);\r
1711 expect(filters.length).toBe(1);\r
1712 expect(collection.filtered).toBe(true);\r
1713 expect(collection.length).toBe(2);\r
1714 expect(collection.items[0]).toBe(item1);\r
1715 expect(collection.items[1]).toBe(item4);\r
1716\r
1717 // item0 matches the filter so should appear in the collection now but\r
1718 // item10 does not match and should be added to the unfiltered collection\r
1719 // instead.\r
1720 collection.add(item0, item10);\r
1721\r
1722 expect(collection.length).toBe(3);\r
1723 expect(collection.items[0]).toBe(item1);\r
1724 expect(collection.items[1]).toBe(item4);\r
1725 expect(collection.items[2]).toBe(item0);\r
1726\r
1727 filters.removeAll();\r
1728\r
1729 expect(refreshes).toBe(2);\r
1730 expect(filters.length).toBe(0);\r
1731 expect(collection.filtered).toBe(false);\r
1732 expect(collection.length).toBe(11);\r
1733 expect(collection.items[0]).toBe(item1);\r
1734 expect(collection.items[1]).toBe(item2);\r
1735 expect(collection.items[2]).toBe(item3);\r
1736 expect(collection.items[3]).toBe(item4);\r
1737 expect(collection.items[4]).toBe(item5);\r
1738 expect(collection.items[5]).toBe(item6);\r
1739 expect(collection.items[6]).toBe(item7);\r
1740 expect(collection.items[7]).toBe(item8);\r
1741 expect(collection.items[8]).toBe(item9);\r
1742 expect(collection.items[9]).toBe(item0);\r
1743 expect(collection.items[10]).toBe(item10);\r
1744 });\r
1745\r
1746 it('should sort the filtered items', function () {\r
1747 var refreshes = 0,\r
1748 filters = collection.getFilters();\r
1749\r
1750 collection.on('refresh', function () {\r
1751 ++refreshes;\r
1752 });\r
1753\r
1754 expect(collection.length).toBe(9);\r
1755 expect(filters.length).toBe(0);\r
1756 expect(collection.filtered).toBe(false);\r
1757\r
1758 filters.add({ property: 'name', value: 'a' });\r
1759\r
1760 expect(refreshes).toBe(1);\r
1761 expect(filters.length).toBe(1);\r
1762 expect(collection.filtered).toBe(true);\r
1763 expect(collection.length).toBe(2);\r
1764 expect(collection.items[0]).toBe(item1);\r
1765 expect(collection.items[1]).toBe(item4);\r
1766\r
1767 // item0 matches the filter so should appear in the collection now but\r
1768 // item10 does not match and should be added to the unfiltered collection\r
1769 // instead.\r
1770 collection.add(item0, item10);\r
1771\r
1772 expect(collection.length).toBe(3);\r
1773 expect(collection.items[0]).toBe(item1);\r
1774 expect(collection.items[1]).toBe(item4);\r
1775 expect(collection.items[2]).toBe(item0);\r
1776\r
1777 collection.sort('name');\r
1778\r
1779 expect(collection.length).toBe(3);\r
1780 expect(collection.items[0]).toBe(item1); // aaa\r
1781 expect(collection.items[1]).toBe(item0); // abba\r
1782 expect(collection.items[2]).toBe(item4); // abc\r
1783\r
1784 filters.removeAll();\r
1785\r
1786 expect(refreshes).toBe(2);\r
1787 expect(filters.length).toBe(0);\r
1788 expect(collection.filtered).toBe(false);\r
1789 expect(collection.length).toBe(11);\r
1790 expect(collection.items[0]).toBe(item1);\r
1791 expect(collection.items[1]).toBe(item0);\r
1792 expect(collection.items[2]).toBe(item4);\r
1793 expect(collection.items[3]).toBe(item2);\r
1794 expect(collection.items[4]).toBe(item5);\r
1795 expect(collection.items[5]).toBe(item3);\r
1796 expect(collection.items[6]).toBe(item6);\r
1797 expect(collection.items[7]).toBe(item9);\r
1798 expect(collection.items[8]).toBe(item8);\r
1799 expect(collection.items[9]).toBe(item10);\r
1800 expect(collection.items[10]).toBe(item7);\r
1801 });\r
1802 }); // single filter\r
1803\r
1804 describe('configurable and detachable', function () {\r
1805 it('should allow filters to be configured', function () {\r
1806 var refreshes = 0;\r
1807\r
1808 collection = new Ext.util.Collection({\r
1809 filters: { property: 'name', value: 'a' },\r
1810 listeners: {\r
1811 refresh: function () {\r
1812 ++refreshes;\r
1813 }\r
1814 }\r
1815 });\r
1816\r
1817 expect(collection.filtered).toBe(true);\r
1818 expect(collection.length).toBe(0);\r
1819\r
1820 var filters = collection.getFilters();\r
1821 expect(filters.length).toBe(1);\r
1822\r
1823 collection.add(item1, item2, item3, item4, item5, item6, item7, item8, item9);\r
1824\r
1825 expect(refreshes).toBe(0);\r
1826 expect(filters.length).toBe(1);\r
1827 expect(collection.filtered).toBe(true);\r
1828 expect(collection.length).toBe(2);\r
1829 expect(collection.items[0]).toBe(item1);\r
1830 expect(collection.items[1]).toBe(item4);\r
1831\r
1832 // item0 matches the filter so should appear in the collection now but\r
1833 // item10 does not match and should be added to the unfiltered collection\r
1834 // instead.\r
1835 collection.add(item0, item10);\r
1836\r
1837 expect(collection.length).toBe(3);\r
1838 expect(collection.items[0]).toBe(item1);\r
1839 expect(collection.items[1]).toBe(item4);\r
1840 expect(collection.items[2]).toBe(item0);\r
1841 });\r
1842\r
1843 it('should allow filters to be detached', function () {\r
1844 var refreshes = 0;\r
1845\r
1846 collection = new Ext.util.Collection({\r
1847 filters: { property: 'name', value: 'a' },\r
1848 listeners: {\r
1849 refresh: function () {\r
1850 ++refreshes;\r
1851 }\r
1852 }\r
1853 });\r
1854\r
1855 expect(collection.filtered).toBe(true);\r
1856 expect(collection.length).toBe(0);\r
1857\r
1858 var filters = collection.getFilters();\r
1859 expect(filters.length).toBe(1);\r
1860\r
1861 collection.add(item1, item2, item3, item4, item5, item6, item7, item8, item9);\r
1862 collection.add(item0, item10);\r
1863\r
1864 //filters.removeAll();\r
1865 collection.setFilters(null);\r
1866\r
1867 expect(refreshes).toBe(1);\r
1868 expect(filters.length).toBe(1);\r
1869 expect(collection.filtered).toBe(false);\r
1870 expect(collection.length).toBe(11);\r
1871 expect(collection.items[0]).toBe(item1);\r
1872 expect(collection.items[1]).toBe(item2);\r
1873 expect(collection.items[2]).toBe(item3);\r
1874 expect(collection.items[3]).toBe(item4);\r
1875 expect(collection.items[4]).toBe(item5);\r
1876 expect(collection.items[5]).toBe(item6);\r
1877 expect(collection.items[6]).toBe(item7);\r
1878 expect(collection.items[7]).toBe(item8);\r
1879 expect(collection.items[8]).toBe(item9);\r
1880 expect(collection.items[9]).toBe(item0);\r
1881 expect(collection.items[10]).toBe(item10);\r
1882\r
1883 collection.setFilters(filters);\r
1884\r
1885 expect(refreshes).toBe(2);\r
1886 expect(filters.length).toBe(1);\r
1887 expect(collection.filtered).toBe(true);\r
1888\r
1889 expect(collection.length).toBe(3);\r
1890 expect(collection.items[0]).toBe(item1);\r
1891 expect(collection.items[1]).toBe(item4);\r
1892 expect(collection.items[2]).toBe(item0);\r
1893 });\r
1894\r
1895 it('should allow detached filters to be manipulated', function () {\r
1896 var refreshes = 0;\r
1897\r
1898 collection = new Ext.util.Collection({\r
1899 filters: { property: 'name', value: 'a' },\r
1900 listeners: {\r
1901 refresh: function () {\r
1902 ++refreshes;\r
1903 }\r
1904 }\r
1905 });\r
1906\r
1907 expect(collection.filtered).toBe(true);\r
1908 expect(collection.length).toBe(0);\r
1909\r
1910 var filters = collection.getFilters();\r
1911 expect(filters.length).toBe(1);\r
1912\r
1913 collection.add(item1, item2, item3, item4, item5, item6, item7, item8, item9);\r
1914 collection.add(item0, item10);\r
1915\r
1916 //filters.removeAll();\r
1917 collection.setFilters(null);\r
1918\r
1919 expect(refreshes).toBe(1);\r
1920 expect(filters.length).toBe(1);\r
1921 expect(collection.filtered).toBe(false);\r
1922 expect(collection.length).toBe(11);\r
1923 expect(collection.items[0]).toBe(item1);\r
1924 expect(collection.items[1]).toBe(item2);\r
1925 expect(collection.items[2]).toBe(item3);\r
1926 expect(collection.items[3]).toBe(item4);\r
1927 expect(collection.items[4]).toBe(item5);\r
1928 expect(collection.items[5]).toBe(item6);\r
1929 expect(collection.items[6]).toBe(item7);\r
1930 expect(collection.items[7]).toBe(item8);\r
1931 expect(collection.items[8]).toBe(item9);\r
1932 expect(collection.items[9]).toBe(item0);\r
1933 expect(collection.items[10]).toBe(item10);\r
1934\r
1935 filters.removeAll();\r
1936 expect(refreshes).toBe(1);\r
1937 expect(filters.length).toBe(0);\r
1938 expect(collection.filtered).toBe(false);\r
1939 expect(collection.length).toBe(11);\r
1940\r
1941 filters.add({ property: 'name', value: 'd' });\r
1942 expect(refreshes).toBe(1);\r
1943 expect(filters.length).toBe(1);\r
1944 expect(collection.filtered).toBe(false);\r
1945 expect(collection.length).toBe(11);\r
1946\r
1947 collection.setFilters(filters);\r
1948\r
1949 expect(refreshes).toBe(2);\r
1950 expect(filters.length).toBe(1);\r
1951 expect(collection.filtered).toBe(true);\r
1952\r
1953 expect(collection.length).toBe(3);\r
1954 expect(collection.items[0]).toBe(item8);\r
1955 expect(collection.items[1]).toBe(item9);\r
1956 expect(collection.items[2]).toBe(item10);\r
1957 });\r
1958 });\r
1959 \r
1960 describe("events", function() {\r
1961 it("should fire the filter event after filtering has taken place", function() {\r
1962 var count;\r
1963 collection.on('filter', function() {\r
1964 count = collection.getCount();\r
1965 });\r
1966 collection.getFilters().add({\r
1967 filterFn: function(item) {\r
1968 return Ext.String.startsWith(item.name, 'a');\r
1969 }\r
1970 });\r
1971 expect(count).toBe(2);\r
1972 });\r
1973 });\r
1974 });\r
1975 \r
1976 describe("grouping", function() {\r
1977 var item0, item1, item2, item3, item4, item5, item6, item7, item8, item9,\r
1978 groups;\r
1979 \r
1980 function groupBy(property, direction) {\r
1981 collection.setGrouper({\r
1982 property: property || 'group',\r
1983 direction: direction\r
1984 });\r
1985 }\r
1986 \r
1987 function clearGroup() {\r
1988 collection.setGrouper(null);\r
1989 }\r
1990 \r
1991 function sortBy(property, direction) {\r
1992 collection.getSorters().add({\r
1993 property: property || 'sortKey',\r
1994 direction: direction\r
1995 });\r
1996 }\r
1997 \r
1998 function filterBy(property, value) {\r
1999 collection.getFilters().add({\r
2000 property: property || 'isFilter',\r
2001 value: Ext.isDefined(value) ? value : true\r
2002 });\r
2003 }\r
2004 \r
2005 beforeEach(function() {\r
2006 collection = new Ext.util.Collection();\r
2007 collection.add(\r
2008 (item0 = {id: 0, name: 'Item0', group: 'A', sortKey: 3, groupOrder: 3, isFilter: false, age: 10}),\r
2009 (item1 = {id: 1, name: 'Item1', group: 'A', sortKey: 1, groupOrder: 3, isFilter: true, age: 30}),\r
2010 (item2 = {id: 2, name: 'Item2', group: 'A', sortKey: 2, groupOrder: 3, isFilter: false, age: 20}),\r
2011 (item3 = {id: 3, name: 'Item3', group: 'B', sortKey: 2, groupOrder: 1, isFilter: true, age: 60}),\r
2012 (item4 = {id: 4, name: 'Item4', group: 'B', sortKey: 3, groupOrder: 1, isFilter: false, age: 50}),\r
2013 (item5 = {id: 5, name: 'Item5', group: 'B', sortKey: 1, groupOrder: 1, isFilter: true, age: 40}),\r
2014 (item6 = {id: 6, name: 'Item6', group: 'C', sortKey: 1, groupOrder: 4, isFilter: false, age: 80}),\r
2015 (item7 = {id: 7, name: 'Item7', group: 'C', sortKey: 2, groupOrder: 4, isFilter: true, age: 70}),\r
2016 (item8 = {id: 8, name: 'Item8', group: 'C', sortKey: 3, groupOrder: 4, isFilter: false, age: 90}),\r
2017 (item9 = {id: 9, name: 'Item9', group: 'D', sortKey: 1, groupOrder: 2, isFilter: true, age: 100})\r
2018 );\r
2019 });\r
2020 \r
2021 afterEach(function() {\r
2022 groups = item0 = item2 = item3 = item4 = item5 = item6 = item7 = item8 = item9 = null;\r
2023 });\r
2024 \r
2025 it("should return an Ext.util.GroupCollection", function() {\r
2026 groupBy();\r
2027 groups = collection.getGroups();\r
2028 expect(groups instanceof Ext.util.GroupCollection).toBe(true);\r
2029 });\r
2030 \r
2031 it("should group by the specified key", function() {\r
2032 groupBy();\r
2033 groups = collection.getGroups();\r
2034 expect(groups.length).toBe(4);\r
2035 });\r
2036 \r
2037 it("should have the appropriate item in each group", function() {\r
2038 groupBy();\r
2039 groups = collection.getGroups();\r
2040 groups.each(function(group) {\r
2041 var key = group.getGroupKey();\r
2042 group.each(function(item) {\r
2043 expect(item.group).toBe(key);\r
2044 });\r
2045 });\r
2046 });\r
2047 \r
2048 describe("clearing groups", function() {\r
2049 it("should return no groups by default", function() {\r
2050 collection = new Ext.util.Collection();\r
2051 expect(collection.getGroups()).toBeNull();\r
2052 }); \r
2053 \r
2054 it("should return no groups once the grouper has cleared", function() {\r
2055 groupBy();\r
2056 collection.getGroups();\r
2057 clearGroup();\r
2058 expect(collection.getGroups()).toBeNull();\r
2059 });\r
2060 });\r
2061 \r
2062 describe("dynamic manipulation", function() {\r
2063 describe("adding", function() {\r
2064 it("should add to an existing group", function() {\r
2065 groupBy();\r
2066 var o = {\r
2067 id: 'new',\r
2068 group: 'D'\r
2069 }, d;\r
2070 \r
2071 collection.add(o);\r
2072 d = collection.getGroups().get('D');\r
2073 expect(d.length).toBe(2);\r
2074 expect(d.contains(o)).toBe(true);\r
2075 });\r
2076 \r
2077 it("should create a new group", function() {\r
2078 groupBy();\r
2079 expect(collection.getGroups().get('E')).toBeUndefined();\r
2080 var o = {\r
2081 id: 'new',\r
2082 group: 'E'\r
2083 }, e;\r
2084 \r
2085 collection.add(o);\r
2086 e = collection.getGroups().get('E');\r
2087 expect(e.length).toBe(1);\r
2088 expect(e.contains(o)).toBe(true);\r
2089 });\r
2090\r
2091 it("should position correctly when adding multiple items", function() {\r
2092 groupBy();\r
2093 var new1 = {\r
2094 id: 'new1',\r
2095 group: 'D'\r
2096 }, new2 = {\r
2097 id: 'new2',\r
2098 group: 'C'\r
2099 };\r
2100\r
2101 collection.add([new1, new2]);\r
2102 expect(collection.indexOf(new1)).toBe(11);\r
2103 expect(collection.indexOf(new2)).toBe(9);\r
2104 });\r
2105 });\r
2106 \r
2107 describe("removing", function() {\r
2108 it("should remove from an existing group", function() {\r
2109 groupBy();\r
2110 collection.remove(item0);\r
2111 var a = collection.getGroups().get('A');\r
2112 expect(a.length).toBe(2);\r
2113 expect(a.contains(item0)).toBe(false);\r
2114 });\r
2115 \r
2116 it("should remove a group", function() {\r
2117 groupBy();\r
2118 collection.remove(item9);\r
2119 expect(collection.getGroups().get('D')).toBeUndefined();\r
2120 });\r
2121 });\r
2122 \r
2123 describe("updating", function() {\r
2124 it("should move the item if the group changes", function() {\r
2125 groupBy();\r
2126 item0.group = 'D';\r
2127 collection.itemChanged(item0);\r
2128 \r
2129 var a = collection.getGroups().get('A'),\r
2130 d = collection.getGroups().get('D');\r
2131 \r
2132 expect(d.length).toBe(2);\r
2133 expect(d.contains(item0)).toBe(true);\r
2134 expect(a.length).toBe(2);\r
2135 expect(a.contains(item0)).toBe(false);\r
2136 });\r
2137\r
2138 it("should position the item correctly in the group", function() {\r
2139 groupBy();\r
2140 item2.group = 'B';\r
2141 // The change in group doesn't change the position of item2, it can remain where it\r
2142 // is because we are not sorted.\r
2143 collection.itemChanged(item2);\r
2144 expect(collection.getGroups().get('B').indexOf(item2)).toBe(0);\r
2145 });\r
2146\r
2147 it("should position if the update is caused by an id change", function() {\r
2148 groupBy();\r
2149 item2.group = 'B';\r
2150 item2.id = 100;\r
2151 collection.updateKey(item2, 2);\r
2152 expect(collection.getGroups().get('B').indexOf(item2)).toBe(0);\r
2153 });\r
2154\r
2155 it("should not exist in the group during a remove if the record is changing position", function() {\r
2156 var removeA, removeB, addA, addB, groups;\r
2157\r
2158 groupBy();\r
2159 groups = collection.getGroups();\r
2160 item9.group = 'B';\r
2161 // The change in group doesn't change the position of item2, it can remain where it\r
2162 // is because we are not sorted.\r
2163 collection.on('remove', function() {\r
2164 removeA = groups.get('A').contains(item9);\r
2165 removeB = groups.get('B').contains(item9);\r
2166 });\r
2167\r
2168 collection.on('add', function() {\r
2169 addA = groups.get('A').contains(item9);\r
2170 addB = groups.get('B').contains(item9);\r
2171 });\r
2172\r
2173 collection.itemChanged(item9);\r
2174 expect(removeA).toBe(false);\r
2175 expect(removeB).toBe(false);\r
2176 expect(addA).toBe(false);\r
2177 expect(addB).toBe(true);\r
2178 });\r
2179 });\r
2180 });\r
2181 \r
2182 describe("sorting", function() {\r
2183 function expectOrder(items, c) {\r
2184 var len = items.length,\r
2185 i;\r
2186 \r
2187 c = c || collection;\r
2188 for (i = 0; i < len; ++i) {\r
2189 expect(c.getAt(i)).toBe(items[i]);\r
2190 }\r
2191 }\r
2192 \r
2193 describe("the groups", function() {\r
2194 function expectGroupOrder(keys) {\r
2195 var groups = collection.getGroups(),\r
2196 len = keys.length,\r
2197 i;\r
2198 \r
2199 for (i = 0; i < len; ++i) {\r
2200 expect(groups.getAt(i).getGroupKey()).toBe(keys[i]);\r
2201 }\r
2202 }\r
2203 \r
2204 it("should sort the groups", function() {\r
2205 collection = new Ext.util.Collection();\r
2206 collection.add(item6, item4, item2, item1, item3, item9, item8, item0, item5, item7);\r
2207 groupBy('group');\r
2208 expectGroupOrder('A', 'B', 'C', 'D');\r
2209 });\r
2210 \r
2211 it("should sort the groups according to the group direction", function() {\r
2212 collection = new Ext.util.Collection();\r
2213 collection.add(item6, item4, item2, item1, item3, item9, item8, item0, item5, item7);\r
2214 groupBy('group', 'DESC');\r
2215 expectGroupOrder('D', 'C', 'B', 'A');\r
2216 });\r
2217 \r
2218 it("should update the group order when the grouper changes", function() {\r
2219 collection = new Ext.util.Collection();\r
2220 collection.add(item6, item4, item2, item1, item3, item9, item8, item0, item5, item7);\r
2221 groupBy('group');\r
2222 groupBy('group', 'DESC');\r
2223 expectGroupOrder('D', 'C', 'B', 'A');\r
2224 });\r
2225 \r
2226 it("should add new groups in the correct position", function() {\r
2227 collection = new Ext.util.Collection();\r
2228 groupBy('group');\r
2229 collection.add(item3);\r
2230 expectGroupOrder(['B']);\r
2231 collection.add(item9);\r
2232 expectGroupOrder(['B', 'D']);\r
2233 collection.add(item6);\r
2234 expectGroupOrder(['B', 'C', 'D']);\r
2235 collection.add(item2);\r
2236 expectGroupOrder(['A', 'B', 'C', 'D']);\r
2237 });\r
2238\r
2239 it("should sort based on the sortProperty", function() {\r
2240 collection.setGrouper({\r
2241 property: 'group',\r
2242 sortProperty: 'groupOrder'\r
2243 });\r
2244 expectGroupOrder(['B', 'D', 'A', 'C']);\r
2245 });\r
2246\r
2247 it("should sort based on the sorterFn", function() {\r
2248 collection.setGrouper({\r
2249 property: 'group',\r
2250 sorterFn: function(a, b) {\r
2251 a = a.groupOrder;\r
2252 b = b.groupOrder;\r
2253 if (a === b) {\r
2254 return 0;\r
2255 }\r
2256 // The order reversal is intentional here\r
2257 return a < b ? 1 : -1;\r
2258 }\r
2259 });\r
2260 expectGroupOrder(['C', 'A', 'D', 'B']);\r
2261 });\r
2262 });\r
2263 \r
2264 describe("inside the groups", function() {\r
2265 it("should sort the items in the collection by group", function() {\r
2266 collection = new Ext.util.Collection();\r
2267 collection.add(item9, item6, item3, item0);\r
2268 groupBy('group', 'ASC');\r
2269 expectOrder([item0, item3, item6, item9]);\r
2270 });\r
2271 \r
2272 it("should sort the groups according to the group direction", function() {\r
2273 collection = new Ext.util.Collection();\r
2274 collection.add(item0, item3, item6, item9);\r
2275 groupBy('group', 'DESC');\r
2276 expectOrder([item9, item6, item3, item0]);\r
2277 });\r
2278 \r
2279 it("should use the natural order inside the groups", function() {\r
2280 collection = new Ext.util.Collection();\r
2281 collection.add(item5, item4, item3, item2, item1, item0);\r
2282 groupBy();\r
2283 expectOrder([item2, item1, item0, item5, item4, item3]);\r
2284 var groups = collection.getGroups();\r
2285 expectOrder([item2, item1, item0], groups.get('A'));\r
2286 expectOrder([item5, item4, item3], groups.get('B'));\r
2287 });\r
2288 \r
2289 it("should insert the record into the correct collection position", function() {\r
2290 collection = new Ext.util.Collection();\r
2291 collection.add({\r
2292 id: 1,\r
2293 name: 'Abe'\r
2294 }, {\r
2295 id: 2,\r
2296 name: 'Tommy'\r
2297 });\r
2298 var nige = {\r
2299 id: 3,\r
2300 name: 'Nige'\r
2301 }; \r
2302 groupBy('name');\r
2303 collection.add(nige);\r
2304 expect(collection.indexOf(nige)).toBe(1);\r
2305 });\r
2306 });\r
2307 \r
2308 describe("with sorters", function() {\r
2309 it("should sort the collection by grouper first", function() {\r
2310 sortBy();\r
2311 groupBy();\r
2312 expectOrder([item1, item2, item0, item5, item3, item4, item6, item7, item8, item9]);\r
2313 });\r
2314 \r
2315 it("should sort the new groups by the sorter", function() {\r
2316 sortBy();\r
2317 groupBy();\r
2318 var groups = collection.getGroups();\r
2319 expectOrder([item1, item2, item0], groups.get('A'));\r
2320 expectOrder([item5, item3, item4], groups.get('B'));\r
2321 expectOrder([item6, item7, item8], groups.get('C'));\r
2322 expectOrder([item9], groups.get('D'));\r
2323 });\r
2324 \r
2325 it("should sort existing groups by the sorter", function() {\r
2326 groupBy();\r
2327 sortBy();\r
2328 var groups = collection.getGroups();\r
2329 expectOrder([item1, item2, item0], groups.get('A'));\r
2330 expectOrder([item5, item3, item4], groups.get('B'));\r
2331 expectOrder([item6, item7, item8], groups.get('C'));\r
2332 expectOrder([item9], groups.get('D'));\r
2333 });\r
2334 \r
2335 it("should sort by the sorter after the groups have been cleared", function() {\r
2336 sortBy();\r
2337 groupBy();\r
2338 clearGroup();\r
2339 expectOrder([item1, item5, item6, item9, item2, item3, item7, item0, item4, item8]);\r
2340 });\r
2341 });\r
2342 });\r
2343 \r
2344 describe("filters", function() {\r
2345 it("should respect existing filters while grouping", function() {\r
2346 filterBy();\r
2347 groupBy();\r
2348 \r
2349 var groups = collection.getGroups(),\r
2350 a = groups.get('A'),\r
2351 b = groups.get('B'),\r
2352 c = groups.get('C'),\r
2353 d = groups.get('D');\r
2354 \r
2355 expect(a.length).toBe(1);\r
2356 expect(a.first()).toBe(item1);\r
2357 \r
2358 expect(b.length).toBe(2);\r
2359 expect(b.first()).toBe(item3);\r
2360 expect(b.last()).toBe(item5);\r
2361 \r
2362 expect(c.length).toBe(1);\r
2363 expect(c.first()).toBe(item7);\r
2364 \r
2365 expect(d.length).toBe(1);\r
2366 expect(d.first()).toBe(item9);\r
2367 });\r
2368 \r
2369 it("should filter existing groups", function() {\r
2370 groupBy();\r
2371 filterBy();\r
2372 \r
2373 var groups = collection.getGroups(),\r
2374 a = groups.get('A'),\r
2375 b = groups.get('B'),\r
2376 c = groups.get('C'),\r
2377 d = groups.get('D');\r
2378 \r
2379 expect(a.length).toBe(1);\r
2380 expect(a.first()).toBe(item1);\r
2381 \r
2382 expect(b.length).toBe(2);\r
2383 expect(b.first()).toBe(item3);\r
2384 expect(b.last()).toBe(item5);\r
2385 \r
2386 expect(c.length).toBe(1);\r
2387 expect(c.first()).toBe(item7);\r
2388 \r
2389 expect(d.length).toBe(1);\r
2390 expect(d.first()).toBe(item9);\r
2391 });\r
2392 \r
2393 it("should update groups when filters are cleared", function() {\r
2394 filterBy();\r
2395 groupBy();\r
2396 \r
2397 collection.getFilters().removeAll();\r
2398 \r
2399 var groups = collection.getGroups();\r
2400 \r
2401 expect(groups.get('A').length).toBe(3);\r
2402 expect(groups.get('B').length).toBe(3);\r
2403 expect(groups.get('C').length).toBe(3);\r
2404 expect(groups.get('D').length).toBe(1);\r
2405 });\r
2406 \r
2407 it("should remove groups when required", function() {\r
2408 groupBy();\r
2409 collection.getFilters().add({\r
2410 filterFn: function(o) {\r
2411 return o.name === 'Item0';\r
2412 }\r
2413 });\r
2414 \r
2415 var groups = collection.getGroups();\r
2416 \r
2417 expect(groups.get('A').length).toBe(1);\r
2418 expect(groups.get('B')).toBeUndefined();\r
2419 expect(groups.get('C')).toBeUndefined();\r
2420 expect(groups.get('D')).toBeUndefined();\r
2421 });\r
2422 \r
2423 it("should add groups when required", function() {\r
2424 groupBy();\r
2425 var filters = collection.getFilters();\r
2426 filters.add({\r
2427 filterFn: function(o) {\r
2428 return Ext.Array.indexOf(['Item0', 'Item9'], o.name) > -1;\r
2429 }\r
2430 }, {\r
2431 filterFn: function(o) {\r
2432 return o.name === 'Item0';\r
2433 }\r
2434 });\r
2435 \r
2436 var groups = collection.getGroups();\r
2437 \r
2438 expect(groups.get('A').length).toBe(1);\r
2439 expect(groups.get('D')).toBeUndefined();\r
2440 \r
2441 filters.remove(filters.last());\r
2442 \r
2443 groups = collection.getGroups();\r
2444 expect(groups.get('A').length).toBe(1);\r
2445 expect(groups.get('D').length).toBe(1);\r
2446 });\r
2447 });\r
2448 \r
2449 describe("aggregation", function() {\r
2450 describe("first", function() {\r
2451 it("should return the first item in each group", function() {\r
2452 groupBy();\r
2453 expect(collection.first(true)).toEqual({\r
2454 A: item0,\r
2455 B: item3,\r
2456 C: item6,\r
2457 D: item9\r
2458 });\r
2459 });\r
2460 \r
2461 it("should ignore the group paramter if not grouped", function() {\r
2462 expect(collection.first(true)).toBe(item0);\r
2463 });\r
2464 });\r
2465 \r
2466 describe("last", function() {\r
2467 it("should return the last item in each group", function() {\r
2468 groupBy();\r
2469 expect(collection.last(true)).toEqual({\r
2470 A: item2,\r
2471 B: item5,\r
2472 C: item8,\r
2473 D: item9\r
2474 });\r
2475 });\r
2476 \r
2477 it("should ignore the group paramter if not grouped", function() {\r
2478 expect(collection.last(true)).toBe(item9);\r
2479 });\r
2480 });\r
2481 \r
2482 describe("average", function() {\r
2483 it("should get the average for each group", function() {\r
2484 groupBy();\r
2485 expect(collection.averageByGroup('age')).toEqual({\r
2486 A: 20,\r
2487 B: 50,\r
2488 C: 80,\r
2489 D: 100\r
2490 });\r
2491 });\r
2492 });\r
2493 \r
2494 describe("bounds", function() {\r
2495 it("should return the bounds for each group", function() {\r
2496 groupBy();\r
2497 expect(collection.boundsByGroup('age')).toEqual({\r
2498 A: [10, 30],\r
2499 B: [40, 60],\r
2500 C: [70, 90],\r
2501 D: [100, 100]\r
2502 });\r
2503 });\r
2504 });\r
2505 \r
2506 describe("count", function() {\r
2507 it("should return the number of items in each group", function() {\r
2508 groupBy();\r
2509 expect(collection.countByGroup()).toEqual({\r
2510 A: 3,\r
2511 B: 3,\r
2512 C: 3,\r
2513 D: 1\r
2514 });\r
2515 });\r
2516 });\r
2517 \r
2518 describe("extremes", function() {\r
2519 it("should return the extremes for each group", function() {\r
2520 groupBy();\r
2521 expect(collection.extremesByGroup('age')).toEqual({\r
2522 A: [item0, item1],\r
2523 B: [item5, item3],\r
2524 C: [item7, item8],\r
2525 D: [item9, item9]\r
2526 });\r
2527 });\r
2528 });\r
2529 \r
2530 describe("max", function() {\r
2531 it("should return the max for each group", function() {\r
2532 groupBy();\r
2533 expect(collection.maxByGroup('age')).toEqual({\r
2534 A: 30,\r
2535 B: 60,\r
2536 C: 90,\r
2537 D: 100\r
2538 });\r
2539 });\r
2540 });\r
2541 \r
2542 describe("maxItem", function() {\r
2543 it("should return the maxItem for each group", function() {\r
2544 groupBy();\r
2545 expect(collection.maxItemByGroup('age')).toEqual({\r
2546 A: item1,\r
2547 B: item3,\r
2548 C: item8,\r
2549 D: item9\r
2550 });\r
2551 });\r
2552 });\r
2553 \r
2554 describe("min", function() {\r
2555 it("should return the min for each group", function() {\r
2556 groupBy();\r
2557 expect(collection.minByGroup('age')).toEqual({\r
2558 A: 10,\r
2559 B: 40,\r
2560 C: 70,\r
2561 D: 100\r
2562 });\r
2563 });\r
2564 });\r
2565 \r
2566 describe("minItem", function() {\r
2567 it("should return the minItem for each group", function() {\r
2568 groupBy();\r
2569 expect(collection.minItemByGroup('age')).toEqual({\r
2570 A: item0,\r
2571 B: item5,\r
2572 C: item7,\r
2573 D: item9\r
2574 });\r
2575 });\r
2576 });\r
2577 \r
2578 describe("sum", function() {\r
2579 it("should return the sum for each group", function() {\r
2580 groupBy();\r
2581 expect(collection.sumByGroup('age')).toEqual({\r
2582 A: 60,\r
2583 B: 150,\r
2584 C: 240,\r
2585 D: 100\r
2586 });\r
2587 });\r
2588 });\r
2589 \r
2590 describe("with a custom aggregator", function() {\r
2591 var fn = function(records, items) {\r
2592 var total = 0,\r
2593 len = items.length,\r
2594 i;\r
2595 \r
2596 for (i = 0; i < len; ++i) {\r
2597 total += (items[i] * 2);\r
2598 }\r
2599 scope = this;\r
2600 return total;\r
2601 }, scope;\r
2602 \r
2603 it("should call the custom aggregator", function() {\r
2604 groupBy();\r
2605 expect(collection.aggregateByGroup('age', fn)).toEqual({\r
2606 A: 120,\r
2607 B: 300,\r
2608 C: 480,\r
2609 D: 200\r
2610 });\r
2611 });\r
2612 \r
2613 it("should use the passed scope", function() {\r
2614 groupBy();\r
2615 collection.aggregateByGroup('age', fn, fakeScope);\r
2616 expect(scope).toBe(fakeScope);\r
2617 });\r
2618 });\r
2619 });\r
2620 });\r
2621\r
2622 describe("sorting", function() {\r
2623 var Ed = { id: 1, name: 'Ed', code: 'C', modifier: 10, firstInitial: 'E' },\r
2624 Abe = { id: 2, name: 'Abe', code: 'A', modifier: 100, firstInitial: 'A' },\r
2625 Edward = { id: 3, name: 'Edward', code: 'B', modifier: 5, firstInitial: 'E' };\r
2626\r
2627 function addItems (c) {\r
2628 c.add(Ed, Abe, Edward);\r
2629 }\r
2630\r
2631 beforeEach(function() {\r
2632 collection = new Ext.util.Collection({\r
2633 keyFn: function(item) {\r
2634 return item.name;\r
2635 }\r
2636 });\r
2637\r
2638 addItems(collection);\r
2639 });\r
2640\r
2641 it('should respect the sorters upon insertion at any index', function() {\r
2642 collection.sort('code');\r
2643 expect(collection.sorted).toBe(true);\r
2644 collection.insert(0, {id: 4, name: 'Nige', code: 'D', modifier: 75, firstInitial: 'N'});\r
2645 expect(collection.items[0].code).toBe('A');\r
2646 expect(collection.items[1].code).toBe('B');\r
2647 expect(collection.items[2].code).toBe('C');\r
2648 expect(collection.items[3].code).toBe('D');\r
2649 });\r
2650\r
2651 it('should clear the sorted flag, and respect insertion point when sorters collection is cleared', function() {\r
2652 collection.sort('code');\r
2653 expect(collection.items[0].code).toBe('A');\r
2654 expect(collection.items[1].code).toBe('B');\r
2655 expect(collection.items[2].code).toBe('C');\r
2656\r
2657 collection.getSorters().clear();\r
2658\r
2659 // Should clear its sorted flag\r
2660 expect(collection.sorted).toBe(false);\r
2661\r
2662 // Insertion at position zero should be respected now that there are no sorters\r
2663 collection.insert(0, {id: 4, name: 'Nige', code: 'D', modifier: 75, firstInitial: 'N'});\r
2664 expect(collection.items[0].code).toBe('D');\r
2665 expect(collection.items[1].code).toBe('A');\r
2666 expect(collection.items[2].code).toBe('B');\r
2667 expect(collection.items[3].code).toBe('C');\r
2668 });\r
2669\r
2670 it("should sort ASC by default", function() {\r
2671 collection.sort('code');\r
2672\r
2673 expect(collection.items[0].code).toBe('A');\r
2674 expect(collection.items[1].code).toBe('B');\r
2675 expect(collection.items[2].code).toBe('C');\r
2676 });\r
2677\r
2678 it("should accept a DESC sort", function() {\r
2679 collection.sort('code', "DESC");\r
2680\r
2681 expect(collection.items[2].code).toBe('A');\r
2682 expect(collection.items[1].code).toBe('B');\r
2683 expect(collection.items[0].code).toBe('C');\r
2684 });\r
2685\r
2686 it("should sort with an Ext.util.Sorter", function() {\r
2687 collection.sort(new Ext.util.Sorter({\r
2688 sorterFn: function(a, b) {\r
2689 return (a.id * a.modifier) - (b.id * b.modifier);\r
2690 }\r
2691 }));\r
2692\r
2693 expect(collection.items[0].code).toBe('C');\r
2694 expect(collection.items[1].code).toBe('B');\r
2695 expect(collection.items[2].code).toBe('A');\r
2696 });\r
2697\r
2698 it("should perform a directional sort with an Ext.util.Sorter", function() {\r
2699 collection.sort(new Ext.util.Sorter({\r
2700 direction: 'DESC',\r
2701 sorterFn: function(a, b) {\r
2702 return (a.id * a.modifier) - (b.id * b.modifier);\r
2703 }\r
2704 }));\r
2705\r
2706 expect(collection.items[2].code).toBe('C');\r
2707 expect(collection.items[1].code).toBe('B');\r
2708 expect(collection.items[0].code).toBe('A');\r
2709 });\r
2710\r
2711 it('should respect configured sorters', function () {\r
2712 var calls = 0;\r
2713\r
2714 collection = new Ext.util.Collection({\r
2715 sorters: 'name'\r
2716 });\r
2717\r
2718 expect(collection.sorted).toBe(true);\r
2719\r
2720 collection.on('sort', function() {\r
2721 ++calls;\r
2722 });\r
2723\r
2724 addItems(collection);\r
2725\r
2726 expect(calls).toBe(0); // should add items in proper order not do full sort\r
2727 expect(collection.length).toBe(3);\r
2728\r
2729 expect(collection.items[0].name).toBe('Abe');\r
2730 expect(collection.items[1].name).toBe('Ed');\r
2731 expect(collection.items[2].name).toBe('Edward');\r
2732\r
2733 // Because we add items to an empty, sorted container a "clever" optimization\r
2734 // is in play and it is easy to end up with the keys out of sync with the\r
2735 // items.\r
2736 expect(collection.getByKey(Abe.id)).toBe(Abe);\r
2737 expect(collection.getByKey(Ed.id)).toBe(Ed);\r
2738 expect(collection.getByKey(Edward.id)).toBe(Edward);\r
2739 });\r
2740\r
2741 it('should merge new items not resort', function () {\r
2742 var adds = [],\r
2743 sorts = 0;\r
2744\r
2745 collection = new Ext.util.Collection({\r
2746 sorters: 'name'\r
2747 });\r
2748\r
2749 expect(collection.sorted).toBe(true);\r
2750\r
2751 collection.on({\r
2752 add: function (sender, details) {\r
2753 adds.push(details.items.length + ' at ' + details.at);\r
2754 },\r
2755 sort: function () {\r
2756 ++sorts;\r
2757 }\r
2758 });\r
2759\r
2760 addItems(collection);\r
2761\r
2762 expect(adds.length).toBe(1);\r
2763 expect(adds.join(' / ')).toBe('3 at 0');\r
2764\r
2765 collection.add([\r
2766 { id: 10, name: 'Nige' },\r
2767 { id: 20, name: 'Evan' },\r
2768 { id: 30, name: 'Don' }\r
2769 ]);\r
2770\r
2771 expect(adds.length).toBe(3);\r
2772 expect(adds.join(' / ')).toBe('3 at 0 / 1 at 1 / 2 at 4');\r
2773\r
2774 expect(sorts).toBe(0); // should add items in proper order not do full sort\r
2775 expect(collection.length).toBe(6);\r
2776 expect(collection.items[0].name).toBe('Abe');\r
2777 expect(collection.items[1].name).toBe('Don');\r
2778 expect(collection.items[2].name).toBe('Ed');\r
2779 expect(collection.items[3].name).toBe('Edward');\r
2780 expect(collection.items[4].name).toBe('Evan');\r
2781 expect(collection.items[5].name).toBe('Nige');\r
2782 });\r
2783\r
2784 it("should fire a sort event", function() {\r
2785 var calls = 0;\r
2786\r
2787 collection.on('sort', function() {\r
2788 ++calls;\r
2789 });\r
2790\r
2791 collection.sort('name');\r
2792\r
2793 expect(calls).toBe(1);\r
2794 });\r
2795\r
2796 it("should sort when sorters is manipulated", function() {\r
2797 expect(collection.sorted).toBe(false);\r
2798 expect(collection.items[0].name).toBe('Ed');\r
2799 expect(collection.items[1].name).toBe('Abe');\r
2800 expect(collection.items[2].name).toBe('Edward');\r
2801\r
2802 collection.getSorters().add('name');\r
2803\r
2804 expect(collection.sorted).toBe(true);\r
2805 expect(collection.items[0].name).toBe('Abe');\r
2806 expect(collection.items[1].name).toBe('Ed');\r
2807 expect(collection.items[2].name).toBe('Edward');\r
2808\r
2809 collection.getSorters().remove('name');\r
2810\r
2811 expect(collection.getSorters().length).toBe(0);\r
2812 expect(collection.sorted).toBe(false);\r
2813 expect(collection.items[0].name).toBe('Abe');\r
2814 expect(collection.items[1].name).toBe('Ed');\r
2815 expect(collection.items[2].name).toBe('Edward');\r
2816 });\r
2817 \r
2818 it("should not fire the sort event when removing all the sorters", function() {\r
2819 var spy = jasmine.createSpy();\r
2820 \r
2821 collection.getSorters().add('name');\r
2822 collection.on('sort', spy);\r
2823 collection.getSorters().remove('name');\r
2824 expect(spy).not.toHaveBeenCalled();\r
2825 });\r
2826\r
2827 it("should sort once per sorter manipulation", function() {\r
2828 var calls = 0,\r
2829 sorters = collection.getSorters();\r
2830\r
2831 collection.on('sort', function() {\r
2832 ++calls;\r
2833 });\r
2834\r
2835 expect(collection.sorted).toBe(false);\r
2836 expect(collection.items[0].name).toBe('Ed');\r
2837 expect(collection.items[1].name).toBe('Abe');\r
2838 expect(collection.items[2].name).toBe('Edward');\r
2839\r
2840 sorters.add(\r
2841 { property: 'firstInitial', direction: 'DESC' },\r
2842 'name');\r
2843\r
2844 expect(calls).toBe(1);\r
2845 expect(sorters.length).toBe(2);\r
2846 expect(collection.sorted).toBe(true);\r
2847 expect(collection.items[0].name).toBe('Ed');\r
2848 expect(collection.items[1].name).toBe('Edward');\r
2849 expect(collection.items[2].name).toBe('Abe');\r
2850\r
2851 sorters.remove('firstInitial');\r
2852\r
2853 expect(calls).toBe(2);\r
2854 expect(sorters.length).toBe(1);\r
2855 expect(collection.sorted).toBe(true);\r
2856 expect(collection.items[0].name).toBe('Abe');\r
2857 expect(collection.items[1].name).toBe('Ed');\r
2858 expect(collection.items[2].name).toBe('Edward');\r
2859\r
2860 sorters.insert(0, { property: 'firstInitial', direction: 'DESC' });\r
2861\r
2862 expect(calls).toBe(3);\r
2863 expect(sorters.length).toBe(2);\r
2864 expect(collection.sorted).toBe(true);\r
2865 expect(collection.items[0].name).toBe('Ed');\r
2866 expect(collection.items[1].name).toBe('Edward');\r
2867 expect(collection.items[2].name).toBe('Abe');\r
2868 });\r
2869\r
2870 it("should enforce multiSortLimit", function() {\r
2871 var calls = 0,\r
2872 sorters = collection.getSorters();\r
2873\r
2874 collection.on('sort', function() {\r
2875 ++calls;\r
2876 });\r
2877\r
2878 collection.setMultiSortLimit(2);\r
2879\r
2880 collection.sort('name', null, 'multi');\r
2881 expect(calls).toBe(1);\r
2882 expect(sorters.length).toBe(1);\r
2883 expect(collection.sorted).toBe(true);\r
2884 expect(sorters.items[0].getProperty()).toBe('name');\r
2885 expect(sorters.items[0].getDirection()).toBe('ASC');\r
2886\r
2887 expect(collection.items[0].name).toBe('Abe');\r
2888 expect(collection.items[1].name).toBe('Ed');\r
2889 expect(collection.items[2].name).toBe('Edward');\r
2890\r
2891 collection.sort('firstInitial', 'DESC', 'multi');\r
2892 expect(calls).toBe(2);\r
2893 expect(sorters.length).toBe(2);\r
2894 expect(collection.sorted).toBe(true);\r
2895 expect(sorters.items[0].getProperty()).toBe('firstInitial');\r
2896 expect(sorters.items[0].getDirection()).toBe('DESC');\r
2897 expect(sorters.items[1].getProperty()).toBe('name');\r
2898 expect(sorters.items[1].getDirection()).toBe('ASC');\r
2899\r
2900 expect(collection.items[0].name).toBe('Ed');\r
2901 expect(collection.items[1].name).toBe('Edward');\r
2902 expect(collection.items[2].name).toBe('Abe');\r
2903\r
2904 // Should toggle direction\r
2905 collection.sort('firstInitial', null, 'multi');\r
2906 expect(calls).toBe(3);\r
2907 expect(sorters.length).toBe(2);\r
2908 expect(collection.sorted).toBe(true);\r
2909 expect(sorters.items[0].getProperty()).toBe('firstInitial');\r
2910 expect(sorters.items[0].getDirection()).toBe('ASC');\r
2911 expect(sorters.items[1].getProperty()).toBe('name');\r
2912 expect(sorters.items[1].getDirection()).toBe('ASC');\r
2913\r
2914 expect(collection.items[0].name).toBe('Abe');\r
2915 expect(collection.items[1].name).toBe('Ed');\r
2916 expect(collection.items[2].name).toBe('Edward');\r
2917\r
2918 // Should respect ASC and not toggle\r
2919 collection.sort('firstInitial', 'ASC', 'multi');\r
2920 expect(calls).toBe(4);\r
2921 expect(sorters.length).toBe(2);\r
2922 expect(collection.sorted).toBe(true);\r
2923 expect(sorters.items[0].getProperty()).toBe('firstInitial');\r
2924 expect(sorters.items[0].getDirection()).toBe('ASC');\r
2925 expect(sorters.items[1].getProperty()).toBe('name');\r
2926 expect(sorters.items[1].getDirection()).toBe('ASC');\r
2927\r
2928 expect(collection.items[0].name).toBe('Abe');\r
2929 expect(collection.items[1].name).toBe('Ed');\r
2930 expect(collection.items[2].name).toBe('Edward');\r
2931\r
2932 // Should bump name to the front and not toggle\r
2933 collection.sort('name', null, 'multi');\r
2934 expect(calls).toBe(5);\r
2935 expect(sorters.length).toBe(2);\r
2936 expect(collection.sorted).toBe(true);\r
2937 expect(sorters.items[0].getProperty()).toBe('name');\r
2938 expect(sorters.items[0].getDirection()).toBe('ASC');\r
2939 expect(sorters.items[1].getProperty()).toBe('firstInitial');\r
2940 expect(sorters.items[1].getDirection()).toBe('ASC');\r
2941\r
2942 expect(collection.items[0].name).toBe('Abe');\r
2943 expect(collection.items[1].name).toBe('Ed');\r
2944 expect(collection.items[2].name).toBe('Edward');\r
2945\r
2946 // Should now toggle name since it is already at the front\r
2947 collection.sort('name', null, 'multi');\r
2948 expect(calls).toBe(6);\r
2949 expect(sorters.length).toBe(2);\r
2950 expect(collection.sorted).toBe(true);\r
2951 expect(sorters.items[0].getProperty()).toBe('name');\r
2952 expect(sorters.items[0].getDirection()).toBe('DESC');\r
2953 expect(sorters.items[1].getProperty()).toBe('firstInitial');\r
2954 expect(sorters.items[1].getDirection()).toBe('ASC');\r
2955\r
2956 expect(collection.items[0].name).toBe('Edward');\r
2957 expect(collection.items[1].name).toBe('Ed');\r
2958 expect(collection.items[2].name).toBe('Abe');\r
2959\r
2960 // Should insert code at the front and clip off firstInitial\r
2961 collection.sort('code', null, 'multi');\r
2962 expect(calls).toBe(7);\r
2963 expect(sorters.length).toBe(2);\r
2964 expect(collection.sorted).toBe(true);\r
2965 expect(sorters.items[0].getProperty()).toBe('code');\r
2966 expect(sorters.items[0].getDirection()).toBe('ASC');\r
2967 expect(sorters.items[1].getProperty()).toBe('name');\r
2968 expect(sorters.items[1].getDirection()).toBe('DESC');\r
2969\r
2970 expect(collection.items[0].name).toBe('Abe');\r
2971 expect(collection.items[1].name).toBe('Edward');\r
2972 expect(collection.items[2].name).toBe('Ed');\r
2973 }); // multiSortLimit\r
2974\r
2975 it('should allow sorter collection removal', function () {\r
2976 var spy = jasmine.createSpy(),\r
2977 sorters = collection.getSorters();\r
2978\r
2979 collection.on('sort', spy);\r
2980\r
2981 collection.sort('name');\r
2982 expect(collection._sorters === sorters).toBe(true);\r
2983 expect(spy.callCount).toBe(1);\r
2984 expect(collection.sorted).toBe(true);\r
2985 expect(collection.items[0].name).toBe('Abe');\r
2986 expect(collection.items[1].name).toBe('Ed');\r
2987 expect(collection.items[2].name).toBe('Edward');\r
2988\r
2989 collection.setSorters(null);\r
2990 expect(collection._sorters === null).toBe(true);\r
2991 expect(collection.sorted).toBe(false);\r
2992 // Should not fire an event, no changes were made to the data\r
2993 expect(spy.callCount).toBe(1);\r
2994 expect(collection.items[0].name).toBe('Abe');\r
2995 expect(collection.items[1].name).toBe('Ed');\r
2996 expect(collection.items[2].name).toBe('Edward');\r
2997\r
2998 collection.sort('code');\r
2999 expect(collection._sorters !== sorters).toBe(true);\r
3000 expect(collection._sorters !== null).toBe(true);\r
3001 expect(spy.callCount).toBe(2);\r
3002 expect(collection.sorted).toBe(true);\r
3003 expect(collection.items[0].name).toBe('Abe');\r
3004 expect(collection.items[1].name).toBe('Edward');\r
3005 expect(collection.items[2].name).toBe('Ed');\r
3006\r
3007 sorters.addSort('name'); // should toggle direction\r
3008 // but disconnected so should not cause the collection to sort\r
3009 expect(spy.callCount).toBe(2);\r
3010 expect(collection.sorted).toBe(true);\r
3011 expect(collection.items[0].name).toBe('Abe');\r
3012 expect(collection.items[1].name).toBe('Edward');\r
3013 expect(collection.items[2].name).toBe('Ed');\r
3014\r
3015 collection.setSorters(sorters);\r
3016 expect(collection._sorters === sorters).toBe(true);\r
3017 expect(collection.sorted).toBe(true);\r
3018 expect(spy.callCount).toBe(3);\r
3019 expect(collection.items[0].name).toBe('Edward');\r
3020 expect(collection.items[1].name).toBe('Ed');\r
3021 expect(collection.items[2].name).toBe('Abe');\r
3022\r
3023 collection.sort('name'); // toggle direction\r
3024 expect(collection._sorters === sorters).toBe(true);\r
3025 expect(spy.callCount).toBe(4);\r
3026 expect(collection.sorted).toBe(true);\r
3027 expect(collection.items[0].name).toBe('Abe');\r
3028 expect(collection.items[1].name).toBe('Ed');\r
3029 expect(collection.items[2].name).toBe('Edward');\r
3030 });\r
3031\r
3032 it("should add items in sorted order when the new items need cloning", function() {\r
3033 collection.removeAll();\r
3034 collection.sort('name', 'DESC');\r
3035 collection.add([Abe, Ed, Edward]);\r
3036 expect(collection.getAt(0)).toBe(Edward);\r
3037 expect(collection.getByKey('Edward')).toBe(Edward);\r
3038 expect(collection.getAt(1)).toBe(Ed);\r
3039 expect(collection.getByKey('Ed')).toBe(Ed);\r
3040 expect(collection.getAt(2)).toBe(Abe);\r
3041 expect(collection.getByKey('Abe')).toBe(Abe);\r
3042 });\r
3043\r
3044 it("should be able to get items by key after inserting multiple items into a sorted collection", function() {\r
3045 collection.getSorters().add('name');\r
3046 var Brian = {id: 4, name: 'Brian'},\r
3047 Aaron = {id: 5, name: 'Aaron'},\r
3048 Fred = {id: 6, name: 'Fred'},\r
3049 Fredward = {id: 7, name: 'Fredward'};\r
3050\r
3051 collection.add(Fredward, Brian, Aaron, Fred);\r
3052 expect(collection.getByKey('Aaron')).toBe(Aaron);\r
3053 expect(collection.getByKey('Brian')).toBe(Brian);\r
3054 expect(collection.getByKey('Fred')).toBe(Fred);\r
3055 expect(collection.getByKey('Fredward')).toBe(Fredward);\r
3056\r
3057 expect(collection.getAt(0)).toBe(Aaron);\r
3058 expect(collection.getAt(1)).toBe(Abe);\r
3059 expect(collection.getAt(2)).toBe(Brian);\r
3060 expect(collection.getAt(3)).toBe(Ed);\r
3061 expect(collection.getAt(4)).toBe(Edward);\r
3062 expect(collection.getAt(5)).toBe(Fred);\r
3063 expect(collection.getAt(6)).toBe(Fredward);\r
3064 });\r
3065\r
3066 it("should be able to remove a sorter instance", function() {\r
3067 var sorter = new Ext.util.Sorter({\r
3068 property: 'name'\r
3069 });\r
3070 var sorters = collection.getSorters();\r
3071 sorters.add(sorter);\r
3072 sorters.remove(sorter);\r
3073 expect(sorters.getCount()).toBe(0);\r
3074 });\r
3075 });\r
3076\r
3077 describe('rootProperty', function () {\r
3078 var Ed = { id: 1, data: { name: 'Ed', code: 'C', modifier: 10, firstInitial: 'E' } },\r
3079 Abe = { id: 2, data: { name: 'Abe', code: 'A', modifier: 100, firstInitial: 'A' } },\r
3080 Edward = { id: 3, data: { name: 'Edward', code: 'B', modifier: 5, firstInitial: 'E' } };\r
3081\r
3082 function addItems (c) {\r
3083 c.add(Edward, Abe, Ed);\r
3084 }\r
3085\r
3086 describe('with extraKeys', function () {\r
3087 it('should properly extract keys', function () {\r
3088 collection = new Ext.util.Collection({\r
3089 rootProperty: 'data',\r
3090 extraKeys: {\r
3091 byName: {\r
3092 property: 'name'\r
3093 }\r
3094 }\r
3095 });\r
3096\r
3097 addItems(collection);\r
3098\r
3099 expect(collection.length).toBe(3);\r
3100 expect(collection.byName.get(Abe.data.name)).toBe(Abe);\r
3101 expect(collection.byName.get(Ed.data.name)).toBe(Ed);\r
3102 expect(collection.byName.get(Edward.data.name)).toBe(Edward);\r
3103\r
3104 collection.clear();\r
3105\r
3106 // clear MUST clear down the extra keys\r
3107 expect(collection.byName.get(Abe.data.name)).toBe(null);\r
3108 });\r
3109 });\r
3110\r
3111 describe('with configured sorters', function () {\r
3112 it('should use the rootProperty', function () {\r
3113 collection = new Ext.util.Collection({\r
3114 rootProperty: 'data',\r
3115 sorters: 'name'\r
3116 });\r
3117\r
3118 addItems(collection);\r
3119\r
3120 expect(collection.length).toBe(3);\r
3121 expect(collection.items[0]).toBe(Abe);\r
3122 expect(collection.items[1]).toBe(Ed);\r
3123 expect(collection.items[2]).toBe(Edward);\r
3124 });\r
3125 });\r
3126\r
3127 describe('with dynamic sorters', function () {\r
3128 it('should use the rootProperty', function () {\r
3129 collection = new Ext.util.Collection({\r
3130 rootProperty: 'data'\r
3131 });\r
3132\r
3133 addItems(collection);\r
3134\r
3135 collection.sort('name');\r
3136\r
3137 expect(collection.length).toBe(3);\r
3138 expect(collection.items[0]).toBe(Abe);\r
3139 expect(collection.items[1]).toBe(Ed);\r
3140 expect(collection.items[2]).toBe(Edward);\r
3141 });\r
3142 });\r
3143\r
3144 describe('with configured filters', function () {\r
3145 it('should use the rootProperty', function () {\r
3146 collection = new Ext.util.Collection({\r
3147 rootProperty: 'data',\r
3148 filters: { property: 'name', value: 'E' }\r
3149 });\r
3150\r
3151 addItems(collection);\r
3152\r
3153 expect(collection.length).toBe(2);\r
3154 //expect(collection.items[0]).toBe(Abe);\r
3155 expect(collection.items[0]).toBe(Edward);\r
3156 expect(collection.items[1]).toBe(Ed);\r
3157 });\r
3158 });\r
3159\r
3160 describe('with dynamic filters', function () {\r
3161 it('should use the rootProperty', function () {\r
3162 collection = new Ext.util.Collection({\r
3163 rootProperty: 'data'\r
3164 });\r
3165\r
3166 addItems(collection);\r
3167\r
3168 collection.setFilters({ property: 'name', value: 'E' });\r
3169\r
3170 expect(collection.length).toBe(2);\r
3171 //expect(collection.items[0]).toBe(Abe);\r
3172 expect(collection.items[0]).toBe(Edward);\r
3173 expect(collection.items[1]).toBe(Ed);\r
3174 });\r
3175 });\r
3176\r
3177 describe('with configured filters and sorters', function () {\r
3178 it('should use the rootProperty', function () {\r
3179 collection = new Ext.util.Collection({\r
3180 rootProperty: 'data',\r
3181 filters: { property: 'name', value: 'E' },\r
3182 sorters: 'name'\r
3183 });\r
3184\r
3185 addItems(collection);\r
3186\r
3187 expect(collection.length).toBe(2);\r
3188 //expect(collection.items[0]).toBe(Abe);\r
3189 expect(collection.items[0]).toBe(Ed);\r
3190 expect(collection.items[1]).toBe(Edward);\r
3191 });\r
3192 });\r
3193\r
3194 describe('with dynamic filters and sorters', function () {\r
3195 it('should use the rootProperty', function () {\r
3196 collection = new Ext.util.Collection({\r
3197 rootProperty: 'data'\r
3198 });\r
3199\r
3200 addItems(collection);\r
3201\r
3202 collection.setFilters({ property: 'name', value: 'E' });\r
3203 collection.sort('name');\r
3204\r
3205 expect(collection.length).toBe(2);\r
3206 //expect(collection.items[0]).toBe(Abe);\r
3207 expect(collection.items[0]).toBe(Ed);\r
3208 expect(collection.items[1]).toBe(Edward);\r
3209 });\r
3210 });\r
3211 });\r
3212\r
3213 describe("extraKeys", function() {\r
3214 var item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10;\r
3215\r
3216 beforeEach(function() {\r
3217 item0 = { id: 0, name: 'abba', uid: '123', foo: 12 };\r
3218 item1 = { id: 1, name: 'aaa', uid: '234', foo: 12 };\r
3219 item2 = { id: 2, name: 'bad', uid: '345', foo: 34 };\r
3220 item3 = { id: 3, name: 'ccc', uid: '456', foo: 34 };\r
3221 item4 = { id: 4, name: 'abc', uid: '678', foo: 24 };\r
3222 item5 = { id: 5, name: 'bcd', uid: '789', foo: 67 };\r
3223 item6 = { id: 6, name: 'cde', uid: '890', foo: 78 };\r
3224 item7 = { id: 7, name: 'xyz', uid: '012', foo: 34 };\r
3225 item8 = { id: 8, name: 'ddd', uid: '246', foo: 34 };\r
3226 item9 = { id: 9, name: 'dad', uid: '468', foo: 24 };\r
3227 item10 = { id: 10, name: 'dood', uid: '680', foo: 24 };\r
3228\r
3229 collection = new Ext.util.Collection({\r
3230 extraKeys: {\r
3231 byUid: 'uid',\r
3232 byFoo: {\r
3233 property: 'foo',\r
3234 unique: false\r
3235 }\r
3236 }\r
3237 });\r
3238\r
3239 collection.add(item0, item1, item2, item3, item4, item5, item6, item7, item8,\r
3240 item9, item10);\r
3241 });\r
3242\r
3243 it('should add items and track unique extraKeys', function () {\r
3244 expect(collection.length).toBe(11);\r
3245\r
3246 expect(collection.byUid.get(item0.uid)).toBe(item0);\r
3247 expect(collection.byUid.get(item1.uid)).toBe(item1);\r
3248 expect(collection.byUid.get(item2.uid)).toBe(item2);\r
3249 expect(collection.byUid.get(item3.uid)).toBe(item3);\r
3250 expect(collection.byUid.get(item4.uid)).toBe(item4);\r
3251 expect(collection.byUid.get(item5.uid)).toBe(item5);\r
3252 expect(collection.byUid.get(item6.uid)).toBe(item6);\r
3253 expect(collection.byUid.get(item7.uid)).toBe(item7);\r
3254 expect(collection.byUid.get(item8.uid)).toBe(item8);\r
3255 expect(collection.byUid.get(item9.uid)).toBe(item9);\r
3256 expect(collection.byUid.get(item10.uid)).toBe(item10);\r
3257 });\r
3258\r
3259 it('should update items on itemChanged', function () {\r
3260 expect(collection.length).toBe(11);\r
3261\r
3262 expect(collection.byUid.get(item0.uid)).toBe(item0);\r
3263 expect(collection.byUid.get(item1.uid)).toBe(item1);\r
3264 expect(collection.byUid.get(item2.uid)).toBe(item2);\r
3265 expect(collection.byUid.get(item3.uid)).toBe(item3);\r
3266 expect(collection.byUid.get(item4.uid)).toBe(item4);\r
3267 expect(collection.byUid.get(item5.uid)).toBe(item5);\r
3268 expect(collection.byUid.get(item6.uid)).toBe(item6);\r
3269 expect(collection.byUid.get(item7.uid)).toBe(item7);\r
3270 expect(collection.byUid.get(item8.uid)).toBe(item8);\r
3271 expect(collection.byUid.get(item9.uid)).toBe(item9);\r
3272 expect(collection.byUid.get(item10.uid)).toBe(item10);\r
3273\r
3274 item0.uid += 'a';\r
3275 collection.itemChanged(item0);\r
3276 \r
3277 expect(collection.byUid.get(item0.uid)).toBe(item0);\r
3278 });\r
3279\r
3280 it('should add items and track non-unique extraKeys', function () {\r
3281 var array12 = collection.byFoo.get(12),\r
3282 array24 = collection.byFoo.get(24),\r
3283 array34 = collection.byFoo.get(34);\r
3284\r
3285 expect(array12.length).toBe(2);\r
3286 expect(array12[0]).toBe(item0);\r
3287 expect(array12[1]).toBe(item1);\r
3288\r
3289 expect(array24.length).toBe(3);\r
3290 expect(array24[0]).toBe(item4);\r
3291 expect(array24[1]).toBe(item9);\r
3292 expect(array24[2]).toBe(item10);\r
3293\r
3294 expect(array34.length).toBe(4);\r
3295 expect(array34[0]).toBe(item2);\r
3296 expect(array34[1]).toBe(item3);\r
3297 expect(array34[2]).toBe(item7);\r
3298 expect(array34[3]).toBe(item8);\r
3299\r
3300 expect(collection.byFoo.get(item5.foo)).toBe(item5);\r
3301 expect(collection.byFoo.get(item6.foo)).toBe(item6);\r
3302 });\r
3303\r
3304 it('should iterate all indices of non-unique extraKeys', function () {\r
3305 var index;\r
3306\r
3307 index = collection.byFoo.indexOf(34);\r
3308 expect(index).toBe(2);\r
3309\r
3310 index = collection.byFoo.indexOf(34, index);\r
3311 expect(index).toBe(3);\r
3312\r
3313 index = collection.byFoo.indexOf(34, index);\r
3314 expect(index).toBe(7);\r
3315\r
3316 index = collection.byFoo.indexOf(34, index);\r
3317 expect(index).toBe(8);\r
3318\r
3319 index = collection.byFoo.indexOf(34, index);\r
3320 expect(index).toBe(-1);\r
3321 });\r
3322\r
3323 it('should iterate one index of unique extraKeys', function () {\r
3324 var index;\r
3325\r
3326 index = collection.byFoo.indexOf(item5.foo);\r
3327 expect(index).toBe(5);\r
3328\r
3329 index = collection.byFoo.indexOf(item5.foo, index);\r
3330 expect(index).toBe(-1);\r
3331 });\r
3332\r
3333 it('should return -1 from indexOf if not found', function () {\r
3334 var index;\r
3335\r
3336 index = collection.byFoo.indexOf(1234);\r
3337 expect(index).toBe(-1);\r
3338 });\r
3339\r
3340 it('should reflect filter state in unique extraKeys', function () {\r
3341 var filters = collection.getFilters();\r
3342\r
3343 expect(collection.length).toBe(11);\r
3344 expect(filters.length).toBe(0);\r
3345 expect(collection.filtered).toBe(false);\r
3346\r
3347 // Check unfiltered first to ensure we don't luck out and create the map on\r
3348 // first call after we apply the filter.\r
3349 expect(collection.byUid.get(item0.uid)).toBe(item0);\r
3350 expect(collection.byUid.get(item1.uid)).toBe(item1);\r
3351 expect(collection.byUid.get(item2.uid)).toBe(item2);\r
3352 expect(collection.byUid.get(item3.uid)).toBe(item3);\r
3353 expect(collection.byUid.get(item4.uid)).toBe(item4);\r
3354 expect(collection.byUid.get(item5.uid)).toBe(item5);\r
3355 expect(collection.byUid.get(item6.uid)).toBe(item6);\r
3356 expect(collection.byUid.get(item7.uid)).toBe(item7);\r
3357 expect(collection.byUid.get(item8.uid)).toBe(item8);\r
3358 expect(collection.byUid.get(item9.uid)).toBe(item9);\r
3359 expect(collection.byUid.get(item10.uid)).toBe(item10);\r
3360\r
3361 function evens (item) {\r
3362 return item.id % 2 === 0;\r
3363 }\r
3364\r
3365 filters.add(evens);\r
3366\r
3367 expect(filters.length).toBe(1);\r
3368 expect(collection.filtered).toBe(true);\r
3369 expect(collection.length).toBe(6);\r
3370 expect(collection.items[0]).toBe(item0);\r
3371 expect(collection.items[1]).toBe(item2);\r
3372 expect(collection.items[2]).toBe(item4);\r
3373 expect(collection.items[3]).toBe(item6);\r
3374 expect(collection.items[4]).toBe(item8);\r
3375 expect(collection.items[5]).toBe(item10);\r
3376\r
3377 // Check that all items are present and those that are filtered out are not.\r
3378 expect(collection.byUid.get(item0.uid)).toBe(item0);\r
3379 expect(collection.byUid.get(item1.uid)).toBe(null);\r
3380 expect(collection.byUid.get(item2.uid)).toBe(item2);\r
3381 expect(collection.byUid.get(item3.uid)).toBe(null);\r
3382 expect(collection.byUid.get(item4.uid)).toBe(item4);\r
3383 expect(collection.byUid.get(item5.uid)).toBe(null);\r
3384 expect(collection.byUid.get(item6.uid)).toBe(item6);\r
3385 expect(collection.byUid.get(item7.uid)).toBe(null);\r
3386 expect(collection.byUid.get(item8.uid)).toBe(item8);\r
3387 expect(collection.byUid.get(item9.uid)).toBe(null);\r
3388 expect(collection.byUid.get(item10.uid)).toBe(item10);\r
3389\r
3390 filters.remove(evens);\r
3391\r
3392 expect(filters.length).toBe(0);\r
3393 expect(collection.filtered).toBe(false);\r
3394 expect(collection.length).toBe(11);\r
3395\r
3396 // Check that all the items are back.\r
3397 expect(collection.byUid.get(item0.uid)).toBe(item0);\r
3398 expect(collection.byUid.get(item1.uid)).toBe(item1);\r
3399 expect(collection.byUid.get(item2.uid)).toBe(item2);\r
3400 expect(collection.byUid.get(item3.uid)).toBe(item3);\r
3401 expect(collection.byUid.get(item4.uid)).toBe(item4);\r
3402 expect(collection.byUid.get(item5.uid)).toBe(item5);\r
3403 expect(collection.byUid.get(item6.uid)).toBe(item6);\r
3404 expect(collection.byUid.get(item7.uid)).toBe(item7);\r
3405 expect(collection.byUid.get(item8.uid)).toBe(item8);\r
3406 expect(collection.byUid.get(item9.uid)).toBe(item9);\r
3407 expect(collection.byUid.get(item10.uid)).toBe(item10);\r
3408 });\r
3409\r
3410 it('should reflect filter state in non-unique extraKeys', function () {\r
3411 var filters = collection.getFilters();\r
3412\r
3413 expect(collection.length).toBe(11);\r
3414 expect(filters.length).toBe(0);\r
3415 expect(collection.filtered).toBe(false);\r
3416\r
3417 // Check unfiltered first to ensure we don't luck out and create the map on\r
3418 // first call after we apply the filter.\r
3419 var array12 = collection.byFoo.get(12),\r
3420 array24 = collection.byFoo.get(24),\r
3421 array34 = collection.byFoo.get(34);\r
3422\r
3423 expect(array12.length).toBe(2);\r
3424 expect(array12[0]).toBe(item0);\r
3425 expect(array12[1]).toBe(item1);\r
3426\r
3427 expect(array24.length).toBe(3);\r
3428 expect(array24[0]).toBe(item4);\r
3429 expect(array24[1]).toBe(item9);\r
3430 expect(array24[2]).toBe(item10);\r
3431\r
3432 expect(array34.length).toBe(4);\r
3433 expect(array34[0]).toBe(item2);\r
3434 expect(array34[1]).toBe(item3);\r
3435 expect(array34[2]).toBe(item7);\r
3436 expect(array34[3]).toBe(item8);\r
3437\r
3438 expect(collection.byFoo.get(item5.foo)).toBe(item5);\r
3439 expect(collection.byFoo.get(item6.foo)).toBe(item6);\r
3440\r
3441 function evens (item) {\r
3442 return item.id % 2 === 0;\r
3443 }\r
3444\r
3445 filters.add(evens);\r
3446\r
3447 expect(filters.length).toBe(1);\r
3448 expect(collection.filtered).toBe(true);\r
3449 expect(collection.length).toBe(6);\r
3450 expect(collection.items[0]).toBe(item0);\r
3451 expect(collection.items[1]).toBe(item2);\r
3452 expect(collection.items[2]).toBe(item4);\r
3453 expect(collection.items[3]).toBe(item6);\r
3454 expect(collection.items[4]).toBe(item8);\r
3455 expect(collection.items[5]).toBe(item10);\r
3456\r
3457 // Check that all items are present and those that are filtered out are not.\r
3458 array12 = collection.byFoo.get(12);\r
3459 array24 = collection.byFoo.get(24);\r
3460 array34 = collection.byFoo.get(34);\r
3461\r
3462 expect(array12).toBe(item0); // not an array any more - just one match\r
3463\r
3464 expect(array24.length).toBe(2);\r
3465 expect(array24[0]).toBe(item4);\r
3466 //expect(array24[1]).toBe(item9);\r
3467 expect(array24[1]).toBe(item10);\r
3468\r
3469 expect(array34.length).toBe(2);\r
3470 expect(array34[0]).toBe(item2);\r
3471 //expect(array34[1]).toBe(item3);\r
3472 //expect(array34[2]).toBe(item7);\r
3473 expect(array34[1]).toBe(item8);\r
3474\r
3475 expect(collection.byFoo.get(item5.foo)).toBe(null);\r
3476 expect(collection.byFoo.get(item6.foo)).toBe(item6);\r
3477\r
3478 filters.remove(evens);\r
3479\r
3480 expect(filters.length).toBe(0);\r
3481 expect(collection.filtered).toBe(false);\r
3482 expect(collection.length).toBe(11);\r
3483\r
3484 // Check that all the items are back.\r
3485 array12 = collection.byFoo.get(12);\r
3486 array24 = collection.byFoo.get(24);\r
3487 array34 = collection.byFoo.get(34);\r
3488\r
3489 expect(array12.length).toBe(2);\r
3490 expect(array12[0]).toBe(item0);\r
3491 expect(array12[1]).toBe(item1);\r
3492\r
3493 expect(array24.length).toBe(3);\r
3494 expect(array24[0]).toBe(item4);\r
3495 expect(array24[1]).toBe(item9);\r
3496 expect(array24[2]).toBe(item10);\r
3497\r
3498 expect(array34.length).toBe(4);\r
3499 expect(array34[0]).toBe(item2);\r
3500 expect(array34[1]).toBe(item3);\r
3501 expect(array34[2]).toBe(item7);\r
3502 expect(array34[3]).toBe(item8);\r
3503\r
3504 expect(collection.byFoo.get(item5.foo)).toBe(item5);\r
3505 expect(collection.byFoo.get(item6.foo)).toBe(item6);\r
3506 });\r
3507 });\r
3508\r
3509 describe("aggregation", function() {\r
3510 describe("simple objects", function() {\r
3511 var item0 = { id: 0, amount: 40 },\r
3512 item1 = { id: 1, amount: 20 },\r
3513 item2 = { id: 2, amount: 10 },\r
3514 item3 = { id: 3, amount: 30 };\r
3515\r
3516 beforeEach(function() {\r
3517 collection = new Ext.util.Collection();\r
3518 collection.add(item0, item1, item2, item3);\r
3519 });\r
3520\r
3521 describe("bounds", function() {\r
3522 it("should operate on all items", function() {\r
3523 expect(collection.bounds('amount')).toEqual([10,40]);\r
3524 });\r
3525\r
3526 it("should support a start index", function() {\r
3527 expect(collection.bounds('amount', 2)).toEqual([10,30]);\r
3528 });\r
3529\r
3530 it("should support a range", function() {\r
3531 expect(collection.bounds('amount', 0, 2)).toEqual([20,40]);\r
3532 });\r
3533 });\r
3534 \r
3535 describe("count", function() {\r
3536 it("should return the count", function() {\r
3537 expect(collection.count()).toBe(4);\r
3538 });\r
3539 });\r
3540\r
3541 describe("extremes", function() {\r
3542 it("should operate on all items", function() {\r
3543 var extremes = collection.extremes('amount');\r
3544 expect(extremes[0]).toBe(item2);\r
3545 expect(extremes[1]).toBe(item0);\r
3546 });\r
3547\r
3548 it("should support a start index", function() {\r
3549 var extremes = collection.extremes('amount', 2);\r
3550 expect(extremes[0]).toBe(item2);\r
3551 expect(extremes[1]).toBe(item3);\r
3552 });\r
3553\r
3554 it("should support a range", function() {\r
3555 var extremes = collection.extremes('amount', 0, 2);\r
3556 expect(extremes[0]).toBe(item1);\r
3557 expect(extremes[1]).toBe(item0);\r
3558 });\r
3559 });\r
3560\r
3561 describe("max", function() {\r
3562 it("should operate on all items", function() {\r
3563 expect(collection.max('amount')).toBe(40);\r
3564 });\r
3565\r
3566 it("should support a start index", function() {\r
3567 expect(collection.max('amount', 2)).toBe(30);\r
3568 });\r
3569\r
3570 it("should support a range", function() {\r
3571 expect(collection.max('amount', 1, 3)).toBe(20);\r
3572 });\r
3573 });\r
3574\r
3575 describe("maxItem", function() {\r
3576 it("should operate on all items", function() {\r
3577 expect(collection.maxItem('amount')).toBe(item0);\r
3578 });\r
3579\r
3580 it("should support a start index", function() {\r
3581 expect(collection.maxItem('amount', 2)).toBe(item3);\r
3582 });\r
3583\r
3584 it("should support a range", function() {\r
3585 expect(collection.maxItem('amount', 1, 3)).toBe(item1);\r
3586 });\r
3587 });\r
3588\r
3589 describe("min", function() {\r
3590 it("should operate on all items", function() {\r
3591 expect(collection.min('amount')).toBe(10);\r
3592 });\r
3593\r
3594 it("should support a start index", function() {\r
3595 expect(collection.min('amount', 2)).toBe(10);\r
3596 });\r
3597\r
3598 it("should support a range", function() {\r
3599 expect(collection.min('amount', 0, 2)).toBe(20);\r
3600 });\r
3601 });\r
3602\r
3603 describe("minItem", function() {\r
3604 it("should operate on all items", function() {\r
3605 expect(collection.minItem('amount')).toBe(item2);\r
3606 });\r
3607\r
3608 it("should support a start index", function() {\r
3609 expect(collection.minItem('amount', 2)).toBe(item2);\r
3610 });\r
3611\r
3612 it("should support a range", function() {\r
3613 expect(collection.minItem('amount', 0, 2)).toBe(item1);\r
3614 });\r
3615 });\r
3616\r
3617 describe("sum", function() {\r
3618 it("should operate on all items", function() {\r
3619 expect(collection.sum('amount')).toBe(100);\r
3620 });\r
3621\r
3622 it("should support a start index", function() {\r
3623 expect(collection.sum('amount', 2)).toBe(40);\r
3624 });\r
3625\r
3626 it("should support a range", function() {\r
3627 expect(collection.sum('amount', 1, 3)).toBe(30);\r
3628 });\r
3629 });\r
3630 });\r
3631\r
3632 describe("complex objects", function() {\r
3633 var item0 = { id: 0, data: { amount: 40 } },\r
3634 item1 = { id: 1, data: { amount: 20 } },\r
3635 item2 = { id: 2, data: { amount: 10 } },\r
3636 item3 = { id: 3, data: { amount: 30 } };\r
3637\r
3638 beforeEach(function() {\r
3639 collection = new Ext.util.Collection({\r
3640 rootProperty: 'data'\r
3641 });\r
3642 collection.add(item0, item1, item2, item3);\r
3643 });\r
3644\r
3645 describe("bounds", function() {\r
3646 it("should operate on all items", function() {\r
3647 expect(collection.bounds('amount')).toEqual([10,40]);\r
3648 });\r
3649\r
3650 it("should support a start index", function() {\r
3651 expect(collection.bounds('amount', 2)).toEqual([10,30]);\r
3652 });\r
3653\r
3654 it("should support a range", function() {\r
3655 expect(collection.bounds('amount', 0, 2)).toEqual([20,40]);\r
3656 });\r
3657 });\r
3658\r
3659 describe("extremes", function() {\r
3660 it("should operate on all items", function() {\r
3661 var extremes = collection.extremes('amount');\r
3662 expect(extremes[0]).toBe(item2);\r
3663 expect(extremes[1]).toBe(item0);\r
3664 });\r
3665\r
3666 it("should support a start index", function() {\r
3667 var extremes = collection.extremes('amount', 2);\r
3668 expect(extremes[0]).toBe(item2);\r
3669 expect(extremes[1]).toBe(item3);\r
3670 });\r
3671\r
3672 it("should support a range", function() {\r
3673 var extremes = collection.extremes('amount', 0, 2);\r
3674 expect(extremes[0]).toBe(item1);\r
3675 expect(extremes[1]).toBe(item0);\r
3676 });\r
3677 });\r
3678\r
3679 describe("max", function() {\r
3680 it("should operate on all items", function() {\r
3681 expect(collection.max('amount')).toBe(40);\r
3682 });\r
3683\r
3684 it("should support a start index", function() {\r
3685 expect(collection.max('amount', 2)).toBe(30);\r
3686 });\r
3687\r
3688 it("should support a range", function() {\r
3689 expect(collection.max('amount', 1, 3)).toBe(20);\r
3690 });\r
3691 });\r
3692\r
3693 describe("maxItem", function() {\r
3694 it("should operate on all items", function() {\r
3695 expect(collection.maxItem('amount')).toBe(item0);\r
3696 });\r
3697\r
3698 it("should support a start index", function() {\r
3699 expect(collection.maxItem('amount', 2)).toBe(item3);\r
3700 });\r
3701\r
3702 it("should support a range", function() {\r
3703 expect(collection.maxItem('amount', 1, 3)).toBe(item1);\r
3704 });\r
3705 });\r
3706\r
3707 describe("min", function() {\r
3708 it("should operate on all items", function() {\r
3709 expect(collection.min('amount')).toBe(10);\r
3710 });\r
3711\r
3712 it("should support a start index", function() {\r
3713 expect(collection.min('amount', 2)).toBe(10);\r
3714 });\r
3715\r
3716 it("should support a range", function() {\r
3717 expect(collection.min('amount', 0, 2)).toBe(20);\r
3718 });\r
3719 });\r
3720\r
3721 describe("minItem", function() {\r
3722 it("should operate on all items", function() {\r
3723 expect(collection.minItem('amount')).toBe(item2);\r
3724 });\r
3725\r
3726 it("should support a start index", function() {\r
3727 expect(collection.minItem('amount', 2)).toBe(item2);\r
3728 });\r
3729\r
3730 it("should support a range", function() {\r
3731 expect(collection.minItem('amount', 0, 2)).toBe(item1);\r
3732 });\r
3733 });\r
3734\r
3735 describe("sum", function() {\r
3736 it("should operate on all items", function() {\r
3737 expect(collection.sum('amount')).toBe(100);\r
3738 });\r
3739\r
3740 it("should support a start index", function() {\r
3741 expect(collection.sum('amount', 2)).toBe(40);\r
3742 });\r
3743\r
3744 it("should support a range", function() {\r
3745 expect(collection.sum('amount', 1, 3)).toBe(30);\r
3746 });\r
3747 });\r
3748 });\r
3749 }); // aggregation\r
3750\r
3751 describe('itemChanged', function () {\r
3752 var events = {\r
3753 add: 0,\r
3754 beforeitemchange: 0,\r
3755 beginupdate: 0,\r
3756 endupdate: 0,\r
3757 itemchange: 0,\r
3758 filtereditemchange: 0,\r
3759 refresh: 0,\r
3760 remove: 0,\r
3761 sort: 0,\r
3762 updatekey: 0\r
3763 };\r
3764 var eventArgs, eventNames, argList;\r
3765 var Don, Evan, Nige, Phil, Kevin;\r
3766\r
3767 function resetEvents () {\r
3768 var listeners = {};\r
3769\r
3770 eventArgs = [];\r
3771 eventNames = [];\r
3772\r
3773 Ext.Object.each(events, function (name) {\r
3774 events[name] = 0;\r
3775 listeners[name] = function () {\r
3776 ++events[name];\r
3777 \r
3778 argList = Ext.Array.slice(arguments, 0);\r
3779\r
3780 // Copy the event info object because two events might use the same object\r
3781 // But mutate a value between the first and second.\r
3782 // eg: Collection#itemChanged fires beforeitemchange and passes a "details" object,\r
3783 // but mutates the "oldIndex" or "newIndex" properties of that object before passing it to the itemchange event.\r
3784 argList[1] = Ext.apply({}, argList[1]);\r
3785\r
3786 eventArgs.push(argList);\r
3787 eventNames.push(name);\r
3788 };\r
3789 });\r
3790\r
3791 return listeners;\r
3792 }\r
3793\r
3794 beforeEach(function () {\r
3795 // Reset these before each test\r
3796 Don = { id: 1, name: 'Don', foo: 10 };\r
3797 Evan = { id: 2, name: 'Evan', foo: 100 };\r
3798 Nige = { id: 3, name: 'Nige', foo: 50 };\r
3799 Phil = { id: 4, name: 'Phil', foo: 30 };\r
3800 Kevin = { id: 5, name: 'Kevin', foo: 30 };\r
3801 });\r
3802\r
3803 describe('unsorted and unfiltered', function () {\r
3804 beforeEach(function () {\r
3805 collection = new Ext.util.Collection({\r
3806 listeners: resetEvents()\r
3807 });\r
3808\r
3809 collection.add(Don, Evan, Nige);\r
3810 resetEvents();\r
3811 });\r
3812\r
3813 it('should not fire add, remove or updatekey when not changed', function () {\r
3814 Don.name = 'Donald';\r
3815\r
3816 collection.itemChanged(Don);\r
3817\r
3818 expect(eventNames.join(',')).\r
3819 toBe('beginupdate,beforeitemchange,itemchange,endupdate');\r
3820\r
3821 var beforeitemchange = eventArgs[1][1],\r
3822 itemchange = eventArgs[2][1];\r
3823\r
3824 // No movement, therefore no adjustment of old/new index in itemchange event\r
3825 expect(beforeitemchange).toEqual(itemchange);\r
3826\r
3827 expect(beforeitemchange.item).toBe(Don);\r
3828 expect(beforeitemchange.filterChanged).toBe(false);\r
3829 expect(beforeitemchange.keyChanged).toBe(false);\r
3830 expect(beforeitemchange.indexChanged).toBe(false);\r
3831 expect(beforeitemchange.modified).toBe(undefined);\r
3832 expect(beforeitemchange.filtered).toBe(false);\r
3833 expect(beforeitemchange.newIndex).toBe(undefined);\r
3834 expect(beforeitemchange.oldIndex).toBe(undefined);\r
3835 expect(beforeitemchange.oldKey).toBe(undefined);\r
3836 expect(beforeitemchange.wasFiltered).toBe(false);\r
3837 });\r
3838\r
3839 it('should fire updatekey and not fire add or remove', function () {\r
3840 var oldKey = Don.id;\r
3841\r
3842 Don.name = 'Donald';\r
3843 Don.id = 10;\r
3844\r
3845 collection.itemChanged(Don, null, oldKey);\r
3846\r
3847 expect(eventNames.join(',')).\r
3848 toBe('beginupdate,beforeitemchange,updatekey,itemchange,endupdate');\r
3849\r
3850 var beforeitemchange = eventArgs[1][1],\r
3851 itemchange = eventArgs[3][1];\r
3852\r
3853 // No movement, therefore no adjustment of old/new index in itemchange event\r
3854 expect(beforeitemchange).toEqual(itemchange);\r
3855\r
3856 expect(beforeitemchange.item).toBe(Don);\r
3857 expect(beforeitemchange.filterChanged).toBe(false);\r
3858 expect(beforeitemchange.keyChanged).toBe(true);\r
3859 expect(beforeitemchange.indexChanged).toBe(false);\r
3860 expect(beforeitemchange.modified).toBe(undefined);\r
3861 expect(beforeitemchange.filtered).toBe(false);\r
3862 expect(beforeitemchange.newIndex).toBe(undefined);\r
3863 expect(beforeitemchange.oldIndex).toBe(undefined);\r
3864 expect(beforeitemchange.oldKey).toBe(oldKey);\r
3865 expect(beforeitemchange.wasFiltered).toBe(false);\r
3866 });\r
3867 }); // unsorted / unfiltered\r
3868\r
3869 describe('sorted and unfiltered', function () {\r
3870 beforeEach(function () {\r
3871 collection = new Ext.util.Collection({\r
3872 listeners: resetEvents(),\r
3873 sorters: 'name'\r
3874 });\r
3875\r
3876 collection.add(Don, Nige, Evan, Phil, Kevin);\r
3877 // Will be\r
3878 // Don, Evan, Kevin, Nige, Phil\r
3879 resetEvents();\r
3880 });\r
3881\r
3882 it('should fire add and remove not updatekey', function () {\r
3883 Don.name = 'Wayne';\r
3884\r
3885 collection.itemChanged(Don);\r
3886\r
3887 expect(eventNames.join(',')).\r
3888 toBe('beginupdate,beforeitemchange,remove,add,itemchange,endupdate');\r
3889\r
3890 var beforeitemchange = eventArgs[1][1];\r
3891\r
3892 expect(beforeitemchange.item).toBe(Don);\r
3893 expect(beforeitemchange.filterChanged).toBe(false);\r
3894 expect(beforeitemchange.keyChanged).toBe(false);\r
3895 expect(beforeitemchange.indexChanged).toBe(true);\r
3896 expect(beforeitemchange.modified).toBe(undefined);\r
3897 expect(beforeitemchange.filtered).toBe(false);\r
3898 expect(beforeitemchange.newIndex).toBe(5);\r
3899 expect(beforeitemchange.oldIndex).toBe(0);\r
3900 expect(beforeitemchange.oldKey).toBe(undefined);\r
3901 expect(beforeitemchange.wasFiltered).toBe(false);\r
3902\r
3903 // Don's name change to Wayne should have moved him to the end\r
3904 expect(collection.items).toEqual([Evan, Kevin, Nige, Phil, Don]);\r
3905 });\r
3906\r
3907 it('should fire updatekey and not fire add or remove', function () {\r
3908 var oldKey = Don.id;\r
3909\r
3910 Don.name = 'Donald';\r
3911 Don.id = 10;\r
3912\r
3913 collection.itemChanged(Don, null, oldKey);\r
3914\r
3915 expect(eventNames.join(',')).\r
3916 toBe('beginupdate,beforeitemchange,updatekey,itemchange,endupdate');\r
3917\r
3918 var beforeitemchange = eventArgs[1][1],\r
3919 itemchange = eventArgs[3][1];\r
3920\r
3921 expect(beforeitemchange).toEqual(itemchange);\r
3922\r
3923 expect(beforeitemchange.item).toBe(Don);\r
3924 expect(beforeitemchange.filterChanged).toBe(false);\r
3925 expect(beforeitemchange.keyChanged).toBe(true);\r
3926 expect(beforeitemchange.indexChanged).toBe(false);\r
3927 expect(beforeitemchange.modified).toBe(undefined);\r
3928 expect(beforeitemchange.filtered).toBe(false);\r
3929 expect(beforeitemchange.newIndex).toBe(undefined);\r
3930 expect(beforeitemchange.oldIndex).toBe(undefined);\r
3931 expect(beforeitemchange.oldKey).toBe(oldKey);\r
3932 expect(beforeitemchange.wasFiltered).toBe(false);\r
3933 });\r
3934\r
3935 it('should order correctly after a sort field change moving to last position', function () {\r
3936 var insertionPoint;\r
3937\r
3938 // Don should move to end\r
3939 Don.name = 'Zaphod';\r
3940\r
3941 collection.on({\r
3942 add: function(coll, adds) {\r
3943 insertionPoint = adds.at;\r
3944 },\r
3945 single: true\r
3946 });\r
3947 collection.itemChanged(Don);\r
3948\r
3949 expect(eventNames.join(',')).\r
3950 toBe('beginupdate,beforeitemchange,remove,add,itemchange,endupdate');\r
3951\r
3952 var beforeitemchange = eventArgs[1][1],\r
3953 itemchange = eventArgs[4][1];\r
3954\r
3955 expect(beforeitemchange.item).toBe(Don);\r
3956 expect(beforeitemchange.filterChanged).toBe(false);\r
3957 expect(beforeitemchange.keyChanged).toBe(false);\r
3958 expect(beforeitemchange.indexChanged).toBe(true);\r
3959 expect(beforeitemchange.modified).toBe(undefined);\r
3960 expect(beforeitemchange.filtered).toBe(false);\r
3961 expect(beforeitemchange.newIndex).toBe(5);\r
3962 expect(insertionPoint).toBe(4);\r
3963 expect(beforeitemchange.oldIndex).toBe(0);\r
3964 expect(beforeitemchange.oldKey).toBe(undefined);\r
3965 expect(beforeitemchange.wasFiltered).toBe(false);\r
3966 \r
3967 expect(itemchange.newIndex).toBe(4);\r
3968\r
3969 // Don's name change to Zaphod should have moved him to the end\r
3970 expect(collection.items).toEqual([Evan, Kevin, Nige, Phil, Don]);\r
3971 });\r
3972\r
3973 it('should order correctly after a sort field change moving to penultimate position', function () {\r
3974 var insertionPoint;\r
3975\r
3976 // Don should move to second from end, before Phil\r
3977 Don.name = 'Owen';\r
3978\r
3979 collection.on({\r
3980 add: function(coll, adds) {\r
3981 insertionPoint = adds.at;\r
3982 },\r
3983 single: true\r
3984 });\r
3985 collection.itemChanged(Don);\r
3986\r
3987 expect(eventNames.join(',')).\r
3988 toBe('beginupdate,beforeitemchange,remove,add,itemchange,endupdate');\r
3989\r
3990 var beforeitemchange = eventArgs[1][1],\r
3991 itemchange = eventArgs[4][1];\r
3992\r
3993 expect(beforeitemchange.item).toBe(Don);\r
3994 expect(beforeitemchange.filterChanged).toBe(false);\r
3995 expect(beforeitemchange.keyChanged).toBe(false);\r
3996 expect(beforeitemchange.indexChanged).toBe(true);\r
3997 expect(beforeitemchange.modified).toBe(undefined);\r
3998 expect(beforeitemchange.filtered).toBe(false);\r
3999 expect(beforeitemchange.newIndex).toBe(4);\r
4000 expect(insertionPoint).toBe(3);\r
4001 expect(beforeitemchange.oldIndex).toBe(0);\r
4002 expect(beforeitemchange.oldKey).toBe(undefined);\r
4003 expect(beforeitemchange.wasFiltered).toBe(false);\r
4004\r
4005 expect(itemchange.newIndex).toBe(3);\r
4006\r
4007 // Don's name change to Owen should have moved him second from the end\r
4008 expect(collection.items).toEqual([Evan, Kevin, Nige, Don, Phil]);\r
4009 });\r
4010\r
4011 it('should order correctly after a sort field change moving to first position', function () {\r
4012 var insertionPoint;\r
4013\r
4014 // Evan should move from second to first, before Don\r
4015 Evan.name = 'Aaron';\r
4016\r
4017 collection.on({\r
4018 add: function(coll, adds) {\r
4019 insertionPoint = adds.at;\r
4020 },\r
4021 single: true\r
4022 });\r
4023 collection.itemChanged(Evan);\r
4024\r
4025 expect(eventNames.join(',')).\r
4026 toBe('beginupdate,beforeitemchange,remove,add,itemchange,endupdate');\r
4027\r
4028 var beforeitemchange = eventArgs[1][1],\r
4029 itemchange = eventArgs[4][1];\r
4030\r
4031 expect(beforeitemchange.item).toBe(Evan);\r
4032 expect(beforeitemchange.filterChanged).toBe(false);\r
4033 expect(beforeitemchange.keyChanged).toBe(false);\r
4034 expect(beforeitemchange.indexChanged).toBe(true);\r
4035 expect(beforeitemchange.modified).toBe(undefined);\r
4036 expect(beforeitemchange.filtered).toBe(false);\r
4037 expect(beforeitemchange.newIndex).toBe(0);\r
4038 expect(insertionPoint).toBe(0);\r
4039 expect(beforeitemchange.oldIndex).toBe(1);\r
4040 expect(beforeitemchange.oldKey).toBe(undefined);\r
4041 expect(beforeitemchange.wasFiltered).toBe(false);\r
4042\r
4043 expect(itemchange.oldIndex).toBe(2);\r
4044\r
4045 // Evan's name change to Aaron should have moved him to first place\r
4046 expect(collection.items).toEqual([Evan, Don, Kevin, Nige, Phil]);\r
4047 });\r
4048\r
4049 it('should order correctly after a sort field change moving to second position', function () {\r
4050 var insertionPoint;\r
4051\r
4052 // Phil should move to 2nd before Evan\r
4053 Phil.name = 'Edgar';\r
4054\r
4055 collection.on({\r
4056 add: function(coll, adds) {\r
4057 insertionPoint = adds.at;\r
4058 },\r
4059 single: true\r
4060 });\r
4061 collection.itemChanged(Phil);\r
4062\r
4063 expect(eventNames.join(',')).\r
4064 toBe('beginupdate,beforeitemchange,remove,add,itemchange,endupdate');\r
4065\r
4066 var beforeitemchange = eventArgs[1][1],\r
4067 itemchange = eventArgs[4][1];\r
4068\r
4069 expect(beforeitemchange.item).toBe(Phil);\r
4070 expect(beforeitemchange.filterChanged).toBe(false);\r
4071 expect(beforeitemchange.keyChanged).toBe(false);\r
4072 expect(beforeitemchange.indexChanged).toBe(true);\r
4073 expect(beforeitemchange.modified).toBe(undefined);\r
4074 expect(beforeitemchange.filtered).toBe(false);\r
4075 expect(beforeitemchange.newIndex).toBe(1);\r
4076 expect(insertionPoint).toBe(1);\r
4077 expect(beforeitemchange.oldIndex).toBe(4);\r
4078 expect(beforeitemchange.oldKey).toBe(undefined);\r
4079 expect(beforeitemchange.wasFiltered).toBe(false);\r
4080\r
4081 expect(itemchange.oldIndex).toBe(5);\r
4082\r
4083 // Phil's name change to Edgar should have moved him to second place\r
4084 expect(collection.items).toEqual([Don, Phil, Evan, Kevin, Nige]);\r
4085 });\r
4086\r
4087 it("should return the correct index when asking for an index during the remove", function() {\r
4088 collection.on('remove', function() {\r
4089 collection.indexOf(Phil);\r
4090 });\r
4091\r
4092 Don.name = 'ZZZ';\r
4093 collection.itemChanged(Don);\r
4094 expect(collection.indexOf(Don)).toBe(4);\r
4095 });\r
4096\r
4097 }); // sorted / unfiltered\r
4098\r
4099 describe('unsorted and filtered', function () {\r
4100 beforeEach(function () {\r
4101 collection = new Ext.util.Collection({\r
4102 listeners: resetEvents(),\r
4103 filters: { property: 'foo', value: 50, operator: '<=' }\r
4104 });\r
4105\r
4106 collection.add(Don, Nige, Evan);\r
4107 resetEvents();\r
4108 });\r
4109\r
4110 it('should remove item once filter applies', function () {\r
4111 expect(collection.length).toBe(2);\r
4112 expect(collection.items[0]).toBe(Don);\r
4113 expect(collection.items[1]).toBe(Nige);\r
4114\r
4115 Don.foo = 75;\r
4116\r
4117 collection.itemChanged(Don);\r
4118\r
4119 expect(collection.length).toBe(1);\r
4120 //expect(collection.items[0]).toBe(Don);\r
4121 expect(collection.items[0]).toBe(Nige);\r
4122\r
4123 expect(eventNames.join(',')).\r
4124 toBe('beginupdate,beforeitemchange,remove,filtereditemchange,endupdate');\r
4125\r
4126 var beforeitemchange = eventArgs[1][1],\r
4127 itemchange = eventArgs[3][1];\r
4128\r
4129 expect(beforeitemchange).toEqual(itemchange);\r
4130\r
4131 expect(beforeitemchange.item).toBe(Don);\r
4132 expect(beforeitemchange.filterChanged).toBe(true);\r
4133 expect(beforeitemchange.keyChanged).toBe(false);\r
4134 expect(beforeitemchange.indexChanged).toBe(false);\r
4135 expect(beforeitemchange.modified).toBe(undefined);\r
4136 expect(beforeitemchange.filtered).toBe(true);\r
4137 expect(beforeitemchange.newIndex).toBe(-1);\r
4138 expect(beforeitemchange.oldIndex).toBe(0);\r
4139 expect(beforeitemchange.oldKey).toBe(undefined);\r
4140 expect(beforeitemchange.wasFiltered).toBe(false);\r
4141 });\r
4142\r
4143 it('should restore item once filter no longer applies', function () {\r
4144 Evan.foo = 5;\r
4145\r
4146 collection.itemChanged(Evan);\r
4147\r
4148 expect(collection.length).toBe(3);\r
4149 expect(collection.items[0]).toBe(Don);\r
4150 expect(collection.items[1]).toBe(Nige);\r
4151 expect(collection.items[2]).toBe(Evan);\r
4152\r
4153 expect(eventNames.join(',')).\r
4154 toBe('beginupdate,beforeitemchange,add,itemchange,endupdate');\r
4155\r
4156 var beforeitemchange = eventArgs[1][1],\r
4157 itemchange = eventArgs[3][1];\r
4158\r
4159 expect(beforeitemchange).toEqual(itemchange);\r
4160\r
4161 expect(beforeitemchange.item).toBe(Evan);\r
4162 expect(beforeitemchange.filterChanged).toBe(true);\r
4163 expect(beforeitemchange.keyChanged).toBe(false);\r
4164 expect(beforeitemchange.indexChanged).toBe(false);\r
4165 expect(beforeitemchange.modified).toBe(undefined);\r
4166 expect(beforeitemchange.filtered).toBe(false);\r
4167 expect(beforeitemchange.newIndex).toBe(2);\r
4168 expect(beforeitemchange.oldIndex).toBe(-1);\r
4169 expect(beforeitemchange.oldKey).toBe(undefined);\r
4170 expect(beforeitemchange.wasFiltered).toBe(true);\r
4171 });\r
4172\r
4173 it("should pass along the modified fields", function() {\r
4174 var spy = jasmine.createSpy();\r
4175 collection.on('beforeitemchange', spy);\r
4176 collection.itemChanged(Evan, ['foo', 'bar']);\r
4177 expect(spy.mostRecentCall.args[1].modified).toEqual(['foo', 'bar']);\r
4178 });\r
4179 }); // unsorted / filtered\r
4180\r
4181 describe('sorted and filtered', function () {\r
4182 beforeEach(function () {\r
4183 collection = new Ext.util.Collection({\r
4184 listeners: resetEvents(),\r
4185 filters: { property: 'foo', value: 50, operator: '<=' },\r
4186 sorters: { property: 'name', direction: 'DESC' }\r
4187 });\r
4188\r
4189 collection.add(Don, Nige, Evan);\r
4190 resetEvents();\r
4191 });\r
4192\r
4193 it('should remove item once filter applies', function () {\r
4194 expect(collection.length).toBe(2);\r
4195 expect(collection.items[0]).toBe(Nige);\r
4196 expect(collection.items[1]).toBe(Don);\r
4197\r
4198 Don.foo = 75;\r
4199\r
4200 collection.itemChanged(Don);\r
4201\r
4202 expect(collection.length).toBe(1);\r
4203 expect(collection.items[0]).toBe(Nige);\r
4204 //expect(collection.items[1]).toBe(Don);\r
4205\r
4206 expect(eventNames.join(',')).\r
4207 toBe('beginupdate,beforeitemchange,remove,filtereditemchange,endupdate');\r
4208\r
4209 var beforeitemchange = eventArgs[1][1],\r
4210 itemchange = eventArgs[3][1];\r
4211\r
4212 expect(beforeitemchange).toEqual(itemchange);\r
4213\r
4214 expect(beforeitemchange.item).toBe(Don);\r
4215 expect(beforeitemchange.filterChanged).toBe(true);\r
4216 expect(beforeitemchange.keyChanged).toBe(false);\r
4217 expect(beforeitemchange.indexChanged).toBe(false);\r
4218 expect(beforeitemchange.modified).toBe(undefined);\r
4219 expect(beforeitemchange.filtered).toBe(true);\r
4220 expect(beforeitemchange.newIndex).toBe(-1);\r
4221 expect(beforeitemchange.oldIndex).toBe(1);\r
4222 expect(beforeitemchange.oldKey).toBe(undefined);\r
4223 expect(beforeitemchange.wasFiltered).toBe(false);\r
4224 });\r
4225\r
4226 it('should restore item once filter no longer applies', function () {\r
4227 Evan.foo = 5;\r
4228\r
4229 collection.itemChanged(Evan);\r
4230\r
4231 expect(collection.length).toBe(3);\r
4232 expect(collection.items[0]).toBe(Nige);\r
4233 expect(collection.items[1]).toBe(Evan);\r
4234 expect(collection.items[2]).toBe(Don);\r
4235\r
4236 expect(eventNames.join(',')).\r
4237 toBe('beginupdate,beforeitemchange,add,itemchange,endupdate');\r
4238\r
4239 var beforeitemchange = eventArgs[1][1],\r
4240 itemchange = eventArgs[3][1];\r
4241\r
4242 expect(beforeitemchange).toEqual(itemchange);\r
4243\r
4244 expect(beforeitemchange.item).toBe(Evan);\r
4245 expect(beforeitemchange.filterChanged).toBe(true);\r
4246 expect(beforeitemchange.keyChanged).toBe(false);\r
4247 expect(beforeitemchange.indexChanged).toBe(false);\r
4248 expect(beforeitemchange.modified).toBe(undefined);\r
4249 expect(beforeitemchange.filtered).toBe(false);\r
4250 expect(beforeitemchange.newIndex).toBe(2);\r
4251 expect(beforeitemchange.oldIndex).toBe(-1);\r
4252 expect(beforeitemchange.oldKey).toBe(undefined);\r
4253 expect(beforeitemchange.wasFiltered).toBe(true);\r
4254 });\r
4255\r
4256 it('should restore item and position once filter no longer applies', function () {\r
4257 Evan.foo = 5;\r
4258 Evan.name = 'ZEvan';\r
4259\r
4260 collection.itemChanged(Evan);\r
4261\r
4262 expect(collection.length).toBe(3);\r
4263 expect(collection.items[0]).toBe(Evan);\r
4264 expect(collection.items[1]).toBe(Nige);\r
4265 expect(collection.items[2]).toBe(Don);\r
4266\r
4267 expect(eventNames.join(',')).\r
4268 toBe('beginupdate,beforeitemchange,add,itemchange,endupdate');\r
4269\r
4270 var beforeitemchange = eventArgs[1][1],\r
4271 itemchange = eventArgs[3][1];\r
4272\r
4273 expect(beforeitemchange).toEqual(itemchange);\r
4274\r
4275 expect(beforeitemchange.item).toBe(Evan);\r
4276 expect(beforeitemchange.filterChanged).toBe(true);\r
4277 expect(beforeitemchange.keyChanged).toBe(false);\r
4278 expect(beforeitemchange.indexChanged).toBe(false);\r
4279 expect(beforeitemchange.modified).toBe(undefined);\r
4280 expect(beforeitemchange.filtered).toBe(false);\r
4281 expect(beforeitemchange.newIndex).toBe(2);\r
4282 expect(beforeitemchange.oldIndex).toBe(-1);\r
4283 expect(beforeitemchange.oldKey).toBe(undefined);\r
4284 expect(beforeitemchange.wasFiltered).toBe(true);\r
4285 });\r
4286 }); // sorted / filtered\r
4287 \r
4288 describe("with a source", function() {\r
4289 it("should pass along the onCollectionItemChanged to the child", function() {\r
4290 var source = new Ext.util.Collection(),\r
4291 spy = jasmine.createSpy(),\r
4292 args;\r
4293 \r
4294 source.add(Don);\r
4295 collection = new Ext.util.Collection({\r
4296 source: source\r
4297 });\r
4298 collection.onCollectionItemChange = spy;\r
4299 \r
4300 source.itemChanged(Don, ['name']);\r
4301 args = spy.mostRecentCall.args;\r
4302 expect(args[0]).toBe(source);\r
4303 expect(args[1].modified).toEqual(['name']);\r
4304 });\r
4305 });\r
4306 }); // itemChanged\r
4307\r
4308 describe("collecting", function() {\r
4309 describe("simple objects", function() {\r
4310 beforeEach(function() {\r
4311 collection = new Ext.util.Collection();\r
4312\r
4313 collection.add([\r
4314 { id: 1, amount: 10, name: 'Ed' },\r
4315 { id: 2, amount: 20, name: 'Abe' },\r
4316 { id: 3, amount: 20, name: 'Ed' }\r
4317 ]);\r
4318 });\r
4319\r
4320 it("should collect the unique properties from each item", function() {\r
4321 var items = collection.collect('name');\r
4322\r
4323 expect(items.length).toBe(2);\r
4324 });\r
4325 });\r
4326\r
4327 describe("complex objects", function() {\r
4328 beforeEach(function() {\r
4329 collection = new Ext.util.Collection();\r
4330\r
4331 collection.add([\r
4332 { id: 1, data: { amount: 10, name: 'Ed' } },\r
4333 { id: 2, data: { amount: 20, name: 'Abe' } },\r
4334 { id: 3, data: { amount: 20, name: 'Ed' } }\r
4335 ]);\r
4336 });\r
4337\r
4338 it("should collect the unique properties from each item", function() {\r
4339 var items = collection.collect('name', 'data');\r
4340\r
4341 expect(items.length).toBe(2);\r
4342 });\r
4343 });\r
4344 });\r
4345\r
4346 describe('adding a Collection to a Collection', function() {\r
4347 it('Should add a Collection as a single new item', function() {\r
4348 var mc1 = new Ext.util.Collection({\r
4349 keyFn: function(object) {\r
4350 return object;\r
4351 }\r
4352 }),\r
4353 mc2 = new Ext.util.Collection();\r
4354\r
4355 mc1.add('b', 'c');\r
4356 mc2.add(mc1); // bug - failed because "length" prop tricked array detection\r
4357 expect(mc2.get(mc1.getId()).indexOf('c')).toBe(1);\r
4358 });\r
4359 });\r
4360\r
4361 describe('adding duplicate items', function() {\r
4362 it('should overwrite duplicates', function() {\r
4363 var mc1 = new Ext.util.Collection();\r
4364 var log = [];\r
4365\r
4366 logEvents(mc1, log, 'text');\r
4367\r
4368 mc1.add({ id: 1, text: 'foo' },\r
4369 { id: 2, text: 'bar' },\r
4370 { id: 1, text: 'bletch' },\r
4371 { id: 2, text: 'zarg' });\r
4372\r
4373 expect(log).toEqual([\r
4374 'beginupdate',\r
4375 'add ["bletch","zarg"] at 0 w/keys [1,2]',\r
4376 'endupdate'\r
4377 ]);\r
4378\r
4379 expect(mc1.getCount()).toBe(2);\r
4380 expect(mc1.getAt(0).text).toBe('bletch');\r
4381 expect(mc1.getAt(1).text).toBe('zarg');\r
4382 });\r
4383 });\r
4384\r
4385 describe('item decoder', function() {\r
4386 it('Should decode new items', function() {\r
4387 var Item = Ext.define(null, {\r
4388 isItem: true,\r
4389 config: {\r
4390 id: null\r
4391 },\r
4392\r
4393 constructor: function (config) {\r
4394 this.initConfig(config);\r
4395 }\r
4396 });\r
4397 var calls = 0;\r
4398 var decoded = 0;\r
4399\r
4400 var mc = new Ext.util.Collection({\r
4401 decoder: function (item) {\r
4402 ++calls;\r
4403 if (!item.isItem) {\r
4404 ++decoded;\r
4405 item = new Item(item);\r
4406 }\r
4407 return item;\r
4408 }\r
4409 });\r
4410\r
4411 mc.add({ id: 42 }, new Item({ id: 'abc' }));\r
4412\r
4413 expect(calls).toBe(2);\r
4414 expect(decoded).toBe(1);\r
4415 expect(mc.items[0].isItem).toBe(true);\r
4416 expect(mc.items[0].getId()).toBe(42);\r
4417 expect(mc.items[1].isItem).toBe(true);\r
4418 expect(mc.items[1].getId()).toBe('abc');\r
4419 });\r
4420 });\r
4421});\r