Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / core / test / unit / spec / lang / Array.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 describe("Ext.Array", function() {
16     var array;
17
18     describe("Ext.Array.indexOf", function() {
19         var indexOf = Ext.Array.indexOf;
20
21         describe("without from argument", function() {
22             beforeEach(function() {
23                 array = [1, 2, 3, 4, 5, 6];
24             });
25
26             afterEach(function(){
27                 array = null;
28             });
29
30             it("should always return -1 on an empty array", function(){
31                 expect(indexOf([], 1)).toEqual(-1);
32             });
33
34             it("should return -1 if them it doesn't exist", function() {
35                 expect(indexOf(array, 7)).toEqual(-1);
36             });
37
38             it("should return the matching index if found", function() {
39                 expect(indexOf(array, 4)).toEqual(3);
40             });
41
42             it("should return the first matching index if found", function(){
43                 array.push(1);
44                 expect(indexOf(array, 1)).toEqual(0);
45             });
46         });
47
48         describe("with from argument", function() {
49             beforeEach(function() {
50                 array = [1, 2, 3, 4, 5, 6, 7];
51             });
52
53             it("should return the matched index if found", function() {
54                 expect(indexOf(array, 5, 3)).toEqual(4);
55             });
56
57             it("should return the matched index if found", function() {
58                 expect(indexOf(array, 5, 4)).toEqual(4);
59             });
60
61             it("should return -1 if the item doesn't exist after the passed from value", function() {
62                 expect(indexOf(array, 5, 5)).toEqual(-1);
63             });
64         });
65
66     });
67     describe("removing items", function() {
68         var remove = Ext.Array.remove,
69             myArray;
70
71         it("should do nothing when removing from an empty array", function() {
72             myArray = [];
73
74             expect(function() {
75                 remove(myArray, 1);
76             }).not.toRaiseExtError();
77
78             expect(myArray).toEqual([]);
79         });
80
81         describe("when removing an item inside an array", function() {
82             beforeEach(function() {
83                 myArray = [1, 2, 3, 4, 5];
84
85                 remove(myArray, 1);
86             });
87
88             it("should remove the item", function() {
89                 expect(myArray).toEqual([2, 3, 4, 5]);
90             });
91
92             it("should update the index of the following items", function() {
93                 expect(myArray[1]).toEqual(3);
94                 expect(myArray[2]).toEqual(4);
95                 expect(myArray[3]).toEqual(5);
96             });
97
98             it("should remove only using a strict type check", function(){
99                 remove(myArray, '2');
100                 expect(myArray).toEqual([2, 3, 4, 5]);
101             });
102         });
103     });
104
105     describe("contains", function() {
106         var contains = Ext.Array.contains;
107
108         it("should always return false with an empty array", function(){
109             expect(contains([], 1)).toBe(false);
110         });
111
112         it("should return false if an item does not exist in the array", function() {
113             expect(contains([1, 2, 3], 10)).toBe(false);
114         });
115
116         it("should return true if an item exists in the array", function() {
117             expect(contains([8, 9, 10], 10)).toBe(true);
118         });
119
120         it("should only match with strict type checking", function(){
121             expect(contains([1, 2, 3, 4, 5], '1')).toBe(false);
122         });
123     });
124
125     describe("include", function(){
126         var include = Ext.Array.include,
127             myArray;
128
129         it("should always add to an empty array", function(){
130             myArray = [];
131             include(myArray, 1);
132             expect(myArray).toEqual([1]);
133         });
134
135         it("should add the item if it doesn't exist", function(){
136             myArray = [1];
137             include(myArray, 2);
138             expect(myArray).toEqual([1, 2]);
139         });
140
141         it("should always add to the end of the array", function(){
142             myArray = [9, 8, 7, 6];
143             include(myArray, 10);
144             expect(myArray).toEqual([9, 8, 7, 6, 10]);
145         });
146
147         it("should match using strict type checking", function(){
148             myArray = ['1'];
149             include(myArray, 1);
150             expect(myArray).toEqual(['1', 1]);
151         });
152
153         it("should not modify the array if the value exists", function(){
154             myArray = [4, 5, 6];
155             include(myArray, 7);
156             expect(myArray).toEqual([4, 5, 6, 7]);
157         });
158     });
159
160     describe("clone", function(){
161         var clone = Ext.Array.clone;
162
163         it("should clone an empty array to be empty", function(){
164             expect(clone([])).toEqual([]);
165         });
166
167         it("should clone an array with items", function(){
168             expect(clone([1, 3, 5])).toEqual([1, 3, 5]);
169         });
170
171         it("should create a new reference", function(){
172             var arr = [1, 2, 3];
173             expect(clone(arr)).not.toBe(arr);
174         });
175
176         it("should do a shallow clone", function(){
177             var o = {},
178                 arr = [o],
179                 result;
180
181             result = clone(arr);
182             expect(result[0]).toBe(o);
183         });
184     });
185
186     describe("clean", function(){
187         var clean = Ext.Array.clean;
188
189         it("should return an empty array if cleaning an empty array", function(){
190             expect(clean([])).toEqual([]);
191         });
192
193         it("should remove undefined values", function(){
194             expect(clean([undefined])).toEqual([]);
195         });
196
197         it("should remove null values", function(){
198             expect(clean([null])).toEqual([]);
199         });
200
201         it("should remove empty strings", function(){
202             expect(clean([''])).toEqual([]);
203         });
204
205         it("should remove empty arrays", function(){
206             expect(clean([[]])).toEqual([]);
207         });
208
209         it("should remove a mixture of empty values", function(){
210             expect(clean([null, undefined, '', []])).toEqual([]);
211         });
212
213         it("should remove all occurrences of empty values", function(){
214             expect(clean([null, null, null, undefined, '', '', '', undefined])).toEqual([]);
215         });
216
217         it("should leave non empty values untouched", function(){
218             expect(clean([1, 2, 3])).toEqual([1, 2, 3]);
219         });
220
221         it("should remove only the empty values", function(){
222             expect(clean([undefined, null, 1, null, 2])).toEqual([1, 2]);
223         });
224
225         it("should preserve order on removal", function(){
226             expect(clean([1, null, 2, null, null, null, 3, undefined, '', '', 4])).toEqual([1, 2, 3, 4]);
227         });
228     });
229
230     describe("unique", function(){
231         var unique = Ext.Array.unique;
232
233         it("should return an empty array if run on an empty array", function(){
234             expect(unique([])).toEqual([]);
235         });
236
237         it("should return a new reference", function(){
238             var arr = [1, 2, 3];
239             expect(unique(arr)).not.toBe(arr);
240         });
241
242         it("should return a copy if all items are unique", function(){
243             expect(unique([6, 7, 8])).toEqual([6, 7, 8]);
244         });
245
246         it("should only use strict typing to match", function(){
247             expect(unique([1, '1'])).toEqual([1, '1']);
248         });
249
250         it("should preserve the order when removing", function(){
251             expect(unique([1, 2, 1, 3, 1, 1, 1, 6, 5, 1])).toEqual([1, 2, 3, 6, 5]);
252         });
253     });
254
255     describe("map", function(){
256         var map = Ext.Array.map,
257             emptyFn = function(v){
258                 return v;
259             };
260
261         it("should return an empty array if run on an empty array", function(){
262             expect(map([], function(){})).toEqual([]);
263         });
264
265         it("should return a new reference", function(){
266             var arr = [1, 2];
267             expect(map(arr, emptyFn)).not.toBe(arr);
268         });
269
270         it("should execute the function for each item in the array", function(){
271             expect(map([1, 2, 3, 4, 5], function(v){
272                 return v * 2;
273             })).toEqual([2, 4, 6, 8, 10]);
274         });
275
276         it("should get called with the correct scope", function(){
277             var scope = {},
278                 realScope;
279             map([1, 2, 3, 4, 5], function(){
280                 realScope = this;
281             }, scope);
282             expect(realScope).toBe(scope);
283         });
284
285         it("should get called with the argument, index and array", function(){
286             var item,
287                 index,
288                 arr,
289                 data = [1];
290
291             map(data, function(){
292                 item = arguments[0];
293                 index = arguments[1];
294                 arr = arguments[2];
295             });
296             expect(item).toEqual(1);
297             expect(index).toEqual(0);
298             expect(arr).toBe(data);
299         });
300     });
301
302     describe("from", function(){
303         var from = Ext.Array.from;
304
305         it("should return an empty array for an undefined value", function(){
306             expect(from(undefined)).toEqual([]);
307         });
308
309         it("should return an empty array for a null value", function(){
310             expect(from(null)).toEqual([]);
311         });
312
313         it("should convert an array", function(){
314             expect(from([1, 2, 3])).toEqual([1, 2, 3]);
315         });
316
317         it("should preserve the order", function(){
318             expect(from(['a', 'string', 'here'])).toEqual(['a', 'string', 'here']);
319         });
320
321         it("should convert a single value to an array", function(){
322             expect(from(true)).toEqual([true]);
323             expect(from(700)).toEqual([700]);
324         });
325
326         it("should convert arguments to an array", function(){
327             var test, fn = function(){
328                 test = from(arguments);
329             };
330             fn(1, 2, 3);
331             expect(test instanceof Array).toBeTruthy();
332             expect(test).toEqual([1, 2, 3]);
333         });
334
335         it("should convert a DOM collection to an array", function(){
336             var ct = document.body.appendChild(document.createElement('div')),
337                 node1 = ct.appendChild(document.createElement('div')),
338                 node2 = ct.appendChild(document.createElement('div')),
339                 node3 = ct.appendChild(document.createElement('div')),
340                 collection = ct.getElementsByTagName('div'),
341                 result = from(collection);
342
343             expect(result instanceof Array).toBeTruthy();
344             expect(result).toEqual([node1, node2, node3]);
345             document.body.removeChild(ct);
346
347         });
348     });
349
350     describe("toArray", function(){
351         var toArray = Ext.Array.toArray;
352
353         it("should convert an array", function(){
354             expect(toArray([1, 2, 3, 4])).toEqual([1, 2, 3, 4]);
355         });
356
357         it("should convert a string", function(){
358             expect(toArray('12345')).toEqual(['1', '2', '3', '4', '5']);
359         });
360
361         it("should create a new reference", function(){
362             var arr = [6, 7, 8];
363             expect(toArray(arr)).not.toBe(arr);
364         });
365
366         it("should convert arguments", function(){
367             var test, fn = function(){
368                 test = toArray(arguments);
369             };
370             fn(-1, -2, -3);
371             expect(test instanceof Array).toBeTruthy();
372             expect(test).toEqual([-1, -2, -3]);
373         });
374
375         it("should convert a DOM collection", function(){
376             var ct = document.body.appendChild(document.createElement('div')),
377                 node1 = ct.appendChild(document.createElement('div')),
378                 node2 = ct.appendChild(document.createElement('div')),
379                 node3 = ct.appendChild(document.createElement('div')),
380                 collection = ct.getElementsByTagName('div'),
381                 result = toArray(collection);
382
383             expect(result instanceof Array).toBeTruthy();
384             expect(result).toEqual([node1, node2, node3]);
385             document.body.removeChild(ct);
386         });
387
388         describe("start/end parameters", function(){
389             it("should default to whole of the array", function(){
390                 expect(toArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
391             });
392
393             it("should work with only the start parameter specified", function(){
394                 expect(toArray([1, 2, 3, 4, 5, 6], 2)).toEqual([3, 4, 5, 6]);
395             });
396
397             it("should work with only the end parameter specified", function(){
398                 expect(toArray([1, 2, 3, 4, 5, 6], null, 4)).toEqual([1, 2, 3, 4]);
399             });
400
401             it("should work with both params specified", function(){
402                 expect(toArray([1, 2, 3, 4, 5, 6], 2, 4)).toEqual([3, 4]);
403             });
404
405             it("should work with nagative end", function(){
406                 expect(toArray([1, 2, 3, 4, 5, 6], 2, -1)).toEqual([3, 4, 5]);
407             });
408         });
409     });
410
411     describe("pluck", function(){
412         var pluck = Ext.Array.pluck;
413         it("should return an empty array when an empty array is passed", function(){
414             expect(pluck([], 'prop')).toEqual([]);
415         });
416
417         it("should pull the properties from objects in the array", function(){
418             var arr = [{prop: 1}, {prop: 2}, {prop: 3}];
419             expect(pluck(arr, 'prop')).toEqual([1, 2, 3]);
420         });
421
422         it("should return a new reference", function(){
423             var arr = [{prop: 1}, {prop: 2}, {prop: 3}];
424             expect(pluck(arr, 'prop')).not.toBe(arr);
425         });
426
427         it("should work on a DOM collection", function(){
428             var ct = document.body.appendChild(document.createElement('div')),
429                 i = 0,
430                 node;
431
432             for(; i < 5; ++i) {
433                 node = ct.appendChild(document.createElement('div'));
434                 node.className = 'node' + i;
435             }
436
437             expect(pluck(ct.getElementsByTagName('div'), 'className')).toEqual(['node0', 'node1', 'node2', 'node3', 'node4']);
438             document.body.removeChild(ct);
439         });
440     });
441
442     describe("filter", function(){
443         var filter = Ext.Array.filter,
444             trueFn = function(){
445                 return true;
446             };
447
448         it("should return an empty array if filtering an empty array", function(){
449             expect(filter([], trueFn)).toEqual([]);
450         });
451
452         it("should create a new reference", function(){
453             var arr = [1, 2, 3];
454             expect(filter(arr, trueFn)).not.toBe(arr);
455         });
456
457         it("should add items if the filter function returns true", function(){
458             expect(filter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(val){
459                 return val % 2 === 0;
460             })).toEqual([2, 4, 6, 8, 10]);
461         });
462
463         it("should add items if the filter function returns a truthy value", function(){
464             expect(filter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(val){
465                 if (val % 2 === 0) {
466                     return 1;
467                 }
468             })).toEqual([2, 4, 6, 8, 10]);
469         });
470
471         it("should not add items if the filter function returns a falsy value", function(){
472             expect(filter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(val){
473                 return 0;
474             })).toEqual([]);
475         });
476
477         it("should pass the correct parameters", function(){
478             var values = [],
479                 indexes = [],
480                 arrs = [],
481                 data = [1, 2, 3];
482
483             filter([1, 2, 3], function(val, index, arr){
484                 values.push(val);
485                 indexes.push(index);
486                 arrs.push(arr);
487             });
488
489             expect(values).toEqual([1, 2, 3]);
490             expect(indexes).toEqual([0, 1, 2]);
491             expect(arrs).toEqual([data, data, data]);
492         });
493
494         it("should do a shallow copy", function(){
495             var o1 = {prop: 1},
496                 o2 = {prop: 2},
497                 o3 = {prop: 3};
498
499             expect(filter([o1, o2, o3], trueFn)).toEqual([o1, o2, o3]);
500         });
501
502         it("should execute in scope when passed", function(){
503             var scope = {},
504                 actual;
505
506             expect(filter([1, 2, 3], function(){
507                 actual = this;
508             }, scope));
509             expect(actual).toBe(scope);
510         });
511     });
512
513     describe("forEach", function(){
514         var forEach = Ext.Array.forEach;
515
516         it("should not execute on an empty array", function(){
517             var count = 0;
518             forEach([], function(){
519                 ++count;
520             });
521             expect(count).toEqual(0);
522         });
523
524         it("should execute for each item in the array", function(){
525             var count = 0;
526             forEach([1, 2, 3, 4, 5], function(){
527                 ++count;
528             });
529             expect(count).toEqual(5);
530         });
531
532         it("should execute in the appropriate scope", function(){
533             var scope = {},
534                 actual;
535
536             forEach([1, 2, 3], function(){
537                 actual = this;
538             }, scope);
539
540             expect(actual).toBe(scope);
541         });
542
543         it("should pass the appropriate params to the callback", function(){
544             var values = [],
545                 indexes = [],
546                 arrs = [],
547                 data = [1, 2, 3];
548
549             forEach(data, function(val, index, arr){
550                 values.push(val);
551                 indexes.push(index);
552                 arrs.push(arr);
553             });
554
555             expect(values).toEqual([1, 2, 3]);
556             expect(indexes).toEqual([0, 1, 2]);
557             expect(arrs).toEqual([data, data, data]);
558         });
559     });
560
561     describe("each", function(){
562         var each = Ext.Array.each;
563
564         describe("return values", function(){
565             xit("should return 0 if the passed value is empty", function(){
566                 expect(each([])).toEqual(0);
567             });
568
569             it("should return the stopping index if iteration is halted", function(){
570                 expect(each([1, 2, 3], function(val){
571                     return val != 2;
572                 })).toEqual(1);
573             });
574
575             it("should return true if iteration is not stopped", function(){
576                 expect(each([4, 5, 6], function(){
577                     return true;
578                 })).toBeTruthy();
579             });
580         });
581
582         describe("scope/parameters", function(){
583             it("should execute in the specified scope", function(){
584                 var scope = {},
585                     actual;
586
587                 each([1, 2, 3], function(){
588                     actual = this;
589                 }, scope);
590                 expect(actual).toBe(scope);
591             });
592
593             it("should pass the item, index and array", function(){
594                 var values = [],
595                     indexes = [],
596                     arrs = [],
597                     data = [1, 2, 3];
598
599                 each(data, function(val, index, arr){
600                     values.push(val);
601                     indexes.push(index);
602                     arrs.push(arr);
603                 });
604
605                 expect(values).toEqual([1, 2, 3]);
606                 expect(indexes).toEqual([0, 1, 2]);
607                 expect(arrs).toEqual([data, data, data]);
608             });
609         });
610
611         describe("stopping iteration", function(){
612             it("should not stop iteration by default", function(){
613                 var count = 0;
614                 each([1, 2, 3, 4, 5], function(){
615                     ++count;
616                 });
617                 expect(count).toEqual(5);
618             });
619
620             it("should not stop unless an explicit false is returned", function(){
621                 var count = 0;
622                 each([1, 2, 3, 4, 5], function(){
623                     ++count;
624                     return null;
625                 });
626                 expect(count).toEqual(5);
627             });
628
629             it("should stop immediately if false is returned", function(){
630                 var count = 0;
631                 each([1, 2, 3, 4, 5], function(v){
632                     ++count;
633                     return v != 2;
634                 });
635                 expect(count).toEqual(2);
636             });
637         });
638
639         describe("other collection types", function(){
640             it("should iterate arguments", function(){
641                 var test, values = [], fn = function(){
642                     test = each(arguments, function(val){
643                         values.push(val);
644                     });
645                 };
646                 fn(1, 2, 3);
647                 expect(values).toEqual([1, 2, 3]);
648             });
649
650             it("should iterate over a DOM collection", function(){
651                 var ct = document.body.appendChild(document.createElement('div')),
652                     node1 = ct.appendChild(document.createElement('div')),
653                     node2 = ct.appendChild(document.createElement('div')),
654                     node3 = ct.appendChild(document.createElement('div')),
655                     collection = ct.getElementsByTagName('div'),
656                     result = [];
657
658                 each(collection, function(node){
659                     result.push(node.tagName.toLowerCase());
660                 });
661
662                 expect(result).toEqual(['div', 'div', 'div']);
663                 document.body.removeChild(ct);
664             });
665         });
666
667         it("should iterate once over a single, non empty value", function(){
668             var count = 0;
669             each('string', function(){
670                 ++count;
671             });
672             expect(count).toEqual(1);
673         });
674     });
675
676     describe("every", function(){
677         var every = Ext.Array.every;
678
679         describe("scope/params", function(){
680             it("should execute in the specified scope", function(){
681                 var scope = {},
682                     actual;
683
684                 every([1, 2, 3], function(){
685                     actual = this;
686                 }, scope);
687                 expect(actual).toBe(scope);
688             });
689
690             it("should pass the item, index and array", function(){
691                 var values = [],
692                     indexes = [],
693                     arrs = [],
694                     data = [1, 2, 3];
695
696                 every(data, function(val, index, arr){
697                     values.push(val);
698                     indexes.push(index);
699                     arrs.push(arr);
700                     return true;
701                 });
702
703                 expect(values).toEqual([1, 2, 3]);
704                 expect(indexes).toEqual([0, 1, 2]);
705                 expect(arrs).toEqual([data, data, data]);
706             });
707         });
708
709         it("should return true on an empty array", function(){
710             expect(every([], function(){})).toBeTruthy();
711         });
712
713         it("should throw an exception if no fn is passed", function(){
714             expect(function(){
715                 every([1, 2, 3]);
716             }).toRaiseExtError();
717         });
718
719         it("should stop as soon as a false value is found", function(){
720             var count = 0,
721                 result;
722
723             result = every([true, true, false, true], function(v){
724                 ++count;
725                 return v;
726             });
727             expect(count).toEqual(3);
728             expect(result).toBeFalsy();
729         });
730
731         it("should return true if all values match the function", function(){
732             expect(every([1, 2, 3, 4, 5, 6, 7, 8, 9], function(v){
733                 return v < 10;
734             })).toBeTruthy();
735         });
736     });
737
738     describe("some", function(){
739         var some = Ext.Array.some;
740
741         describe("scope/params", function(){
742             it("should execute in the specified scope", function(){
743                 var scope = {},
744                     actual;
745
746                 some([1, 2, 3], function(){
747                     actual = this;
748                 }, scope);
749                 expect(actual).toBe(scope);
750             });
751
752             it("should pass the item, index and array", function(){
753                 var values = [],
754                     indexes = [],
755                     arrs = [],
756                     data = [1, 2, 3];
757
758                 some(data, function(val, index, arr){
759                     values.push(val);
760                     indexes.push(index);
761                     arrs.push(arr);
762                     return true;
763                 });
764
765                 expect(values).toEqual([1]);
766                 expect(indexes).toEqual([0]);
767                 expect(arrs).toEqual([data]);
768             });
769         });
770
771         it("should return false on an empty array", function(){
772             expect(some([], function(){})).toBeFalsy();
773         });
774
775         it("should throw an exception if no fn is passed", function(){
776             expect(function(){
777                 some([1, 2, 3]);
778             }).toRaiseExtError();
779         });
780
781         it("should stop as soon as a matching value is found", function(){
782             var count = 0,
783                 result;
784
785             result = some([1, 2, 3, 4], function(val){
786                 ++count;
787                 return val == 3;
788             });
789             expect(count).toEqual(3);
790             expect(result).toBeTruthy();
791         });
792
793         it("should return false if nothing matches the matcher function", function(){
794             var count = 0,
795                 result;
796
797             result = some([1, 2, 3, 4, 5, 6, 7, 8, 9], function(val){
798                 ++count;
799                 return val > 9;
800             });
801             expect(count).toEqual(9);
802             expect(result).toBeFalsy();
803         });
804     });
805
806     describe("merge", function(){
807         var merge = Ext.Array.merge;
808
809         it("should return an empty array if run on an empty array", function(){
810             expect(merge([])).toEqual([]);
811         });
812
813         it("should return a new reference", function(){
814             var arr = [1, 2, 3];
815             expect(merge(arr)).not.toBe(arr);
816         });
817
818         it("should return a copy if all items are unique", function(){
819             expect(merge([6, 7, 8])).toEqual([6, 7, 8]);
820         });
821
822         it("should only use strict typing to match", function(){
823             expect(merge([1, '1'])).toEqual([1, '1']);
824         });
825
826         it("should accept two or more arrays and return a unique union with items in order of first appearance", function(){
827             expect(merge([1, 2, 3], ['1', '2', '3'], [4, 1, 5, 2], [6, 3, 7, '1'], [8, '2', 9, '3'])).toEqual([1, 2, 3, '1', '2', '3', 4, 5, 6, 7, 8, 9]);
828         });
829     });
830
831     describe("intersect", function(){
832         var intersect = Ext.Array.intersect;
833
834         it("should return an empty array if no arrays are passed", function(){
835             expect(intersect()).toEqual([]);
836         });
837
838         it("should return an empty array if one empty array is passed", function(){
839             expect(intersect([])).toEqual([]);
840         });
841
842         it("should return a new reference", function(){
843             var arr = [1, 2, 3];
844             expect(intersect(arr)).not.toBe(arr);
845         });
846
847         it("should return a copy if one array is passed", function(){
848             expect(intersect([6, 7, 8])).toEqual([6, 7, 8]);
849         });
850
851         it("should return an intersection of two or more arrays with items in order of first appearance", function(){
852             expect(intersect([1, 2, 3], [4, 3, 2, 5], [2, 6, 3])).toEqual([2, 3]);
853         });
854
855         it("should return an empty array if there is no intersecting values", function(){
856             expect(intersect([1, 2, 3], [4, 5, 6])).toEqual([]);
857         });
858
859         it("should contain the unique set of intersected values only", function(){
860             expect(intersect([1, 1, 2, 3, 3], [1, 1, 2, 3, 3])).toEqual([1, 2, 3]);
861         });
862
863         it("should only use strict typing to match", function(){
864             expect(intersect([1], ['1'])).toEqual([]);
865         });
866     });
867
868     describe("difference", function(){
869         var difference = Ext.Array.difference;
870
871         it("should return a set difference of two arrays with items in order of first appearance", function(){
872             expect(difference([1, 2, 3, 4], [3, 2])).toEqual([1, 4]);
873         });
874
875         it("should return the first array unchanged if there is no difference", function(){
876             expect(difference([1, 2, 3], [4, 5, 6])).toEqual([1, 2, 3]);
877         });
878
879         it("should return a new reference", function(){
880             var arr = [1, 2, 3];
881             expect(difference(arr, [3, 2])).not.toBe(arr);
882         });
883
884         it("should remove multiples of the same value from the first array", function(){
885             expect(difference([1, 2, 3, 2, 4, 1], [2, 1])).toEqual([3, 4]);
886         });
887
888         it("should only use strict typing to match", function(){
889             expect(difference([1], ['1'])).toEqual([1]);
890         });
891     });
892
893     describe("sort", function() {
894        var sarray, narray;
895        beforeEach(function() {
896           sarray = ['bbb', 'addda', 'erere', 'fff', 'de3'];
897           narray = [1,3,2,4,6,7];
898
899        });
900
901        describe("with strings", function() {
902            it("should be able to sort an array without sortFn", function() {
903                 Ext.Array.sort(sarray);
904                 expect(sarray).toEqual(['addda', 'bbb', 'de3', 'erere', 'fff']);
905            });
906
907
908            it("should be able to use a sortFn that returns a Number", function() {
909                 Ext.Array.sort(sarray, function(a,b){ 
910                     if (a === b) {
911                         return 0;
912                     } 
913                     return  a > b ? 1: -1;
914                 });
915                 expect(sarray).toEqual(['addda', 'bbb', 'de3', 'erere', 'fff']);
916            });
917        });
918
919        describe("with numbers", function() {
920            it("should be able to sort an array without sortFn", function() {
921                 Ext.Array.sort(narray);
922                 expect(narray).toEqual([1,2,3,4,6,7]);
923            });
924
925
926            it("should be able to use a sortFn that returns a Number", function() {
927                 Ext.Array.sort(narray, function(a,b){
928                     return a - b;
929                 });
930                 expect(narray).toEqual([1,2,3,4,6,7]);
931            });
932        });
933     });
934
935     describe("min", function() {
936         describe("numbers", function() {
937             it("without comparisonFn", function() {
938                 expect(Ext.Array.min([1,2,3,4,5,6])).toEqual(1);
939             });
940
941             it("with comparisonFn", function() {
942                 expect(Ext.Array.min([1,2,3,4,5,6], function(a, b) { return a < b ? 1 : -1; })).toEqual(6);
943             });
944         });
945     });
946
947     describe("max", function() {
948         describe("numbers", function() {
949             it("without comparisonFn", function() {
950                 expect(Ext.Array.max([1,2,3,4,5,6])).toEqual(6);
951             });
952
953             it("with comparisonFn", function() {
954                 expect(Ext.Array.max([1,2,3,4,5,6], function(a, b) { return a < b ? 1 : -1; })).toEqual(1);
955             });
956         });
957     });
958
959     describe("sum", function() {
960         it("should return 21", function() {
961             expect(Ext.Array.sum([1,2,3,4,5,6])).toEqual(21);
962         });
963     });
964
965     describe("mean", function() {
966         it("should return 3.5", function() {
967             expect(Ext.Array.mean([1,2,3,4,5,6])).toEqual(3.5);
968         });
969     });
970
971     function testReplace (replace) {
972         it('should remove items in the middle', function () {
973             var array = [0, 1, 2, 3, 4, 5, 6, 7];
974             replace(array, 2, 2);
975             expect(Ext.encode(array)).toEqual('[0,1,4,5,6,7]');
976         });
977         it('should insert items in the middle', function () {
978             var array = [0, 1, 2, 3, 4, 5, 6, 7];
979             replace(array, 2, 0, ['a','b']);
980             expect(Ext.encode(array)).toEqual('[0,1,"a","b",2,3,4,5,6,7]');
981         });
982         it('should replace in the middle with more items', function () {
983             var array = [0, 1, 2, 3, 4, 5, 6, 7];
984             replace(array, 2, 2, ['a','b', 'c', 'd']);
985             expect(Ext.encode(array)).toEqual('[0,1,"a","b","c","d",4,5,6,7]');
986         });
987         it('should replace in the middle with fewer items', function () {
988             var array = [0, 1, 2, 3, 4, 5, 6, 7];
989             replace(array, 2, 4, ['a','b']);
990             expect(Ext.encode(array)).toEqual('[0,1,"a","b",6,7]');
991         });
992         it('should delete at front', function () {
993             var array = [0, 1, 2, 3];
994             replace(array, 0, 2);
995             expect(Ext.encode(array)).toEqual('[2,3]');
996         });
997         it('should delete at tail', function () {
998             var array = [0, 1, 2, 3];
999             replace(array, 2, 2);
1000             expect(Ext.encode(array)).toEqual('[0,1]');
1001         });
1002         it('should delete everything', function () {
1003             var array = [0, 1, 2, 3];
1004             replace(array, 0, 4);
1005             expect(Ext.encode(array)).toEqual('[]');
1006         });
1007         it('should insert at front', function () {
1008             var array = [0, 1];
1009             replace(array, 0, 0, ['a','b','c','d','e']);
1010             expect(Ext.encode(array)).toEqual('["a","b","c","d","e",0,1]');
1011         });
1012         it('should insert at tail', function () {
1013             var array = [0, 1];
1014             replace(array, array.length, 0, ['a','b','c','d','e']);
1015             expect(Ext.encode(array)).toEqual('[0,1,"a","b","c","d","e"]');
1016         });
1017         it('should insert into empty array', function () {
1018             var array = [];
1019             replace(array, 0, 0, ['a','b','c','d','e']);
1020             expect(Ext.encode(array)).toEqual('["a","b","c","d","e"]');
1021         });
1022         it('should replace at front', function () {
1023             var array = [0, 1];
1024             replace(array, 0, 1, ['a','b','c','d','e']);
1025             expect(Ext.encode(array)).toEqual('["a","b","c","d","e",1]');
1026         });
1027         it('should replace at tail', function () {
1028             var array = [0, 1];
1029             replace(array, 1, 1, ['a','b','c','d','e']);
1030             expect(Ext.encode(array)).toEqual('[0,"a","b","c","d","e"]');
1031         });
1032         it('should replace entire array', function () {
1033             var array = [0, 1, 2, 3];
1034             replace(array, 0, array.length, ['a','b','c','d','e']);
1035             expect(Ext.encode(array)).toEqual('["a","b","c","d","e"]');
1036         });
1037         it('should handle negative index', function () {
1038             var array = [0, 1, 2, 3];
1039             replace(array, -2, 20); // should clip
1040             expect(Ext.encode(array)).toEqual('[0,1]');
1041         });
1042         it('should work around the IE8 bug', function () {
1043             // see http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/6e946d03-e09f-4b22-a4dd-cd5e276bf05a/
1044             var array = [],
1045                 lengthBefore,
1046                 j = 20;
1047
1048             while (j--) {
1049                 array.push("A");
1050             }
1051
1052             array.splice(15, 0, "F", "F", "F", "F", "F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F");
1053             // the fact that this is an APPLY is not instrumental to reproducing this bug
1054
1055             lengthBefore = array.length; // = 41
1056
1057             // everything above should be exactly preserved including the true splice call.
1058             // That way we have produced the Array Time Bomb... now see if it explodes!
1059
1060             replace(array, 13, 0, ["XXX"]); // add one element (this was the failure)
1061
1062             expect(array.length).toEqual(lengthBefore+1);
1063         });
1064     }
1065
1066     describe('replaceSim', function () {
1067         // The _replace method is our corrected method for IE8, but we make it available (in
1068         // debug builds) on all browsers to see that it works.
1069         testReplace(Ext.Array._replaceSim);
1070     });
1071
1072     describe('replaceNative', function () {
1073         // and test the wrapper on other browsers
1074         testReplace(Ext.Array.replace);
1075     });
1076
1077     describe('splice', function () {
1078         it('returns proper result array at the front', function () {
1079             var ret = Ext.Array._spliceSim([1,2,3,4], 0, 2);
1080             expect(Ext.encode(ret)).toEqual('[1,2]');
1081         });
1082         it('returns proper result array at the end', function () {
1083             var ret = Ext.Array._spliceSim([1,2,3,4], 2, 2);
1084             expect(Ext.encode(ret)).toEqual('[3,4]');
1085         });
1086         it('returns proper result array from the middle', function () {
1087             var ret = Ext.Array._spliceSim([1,2,3,4], 1, 2);
1088             expect(Ext.encode(ret)).toEqual('[2,3]');
1089         });
1090         it('return an empty array when nothing removed', function () {
1091             var ret = Ext.Array._spliceSim([1,2,3,4], 1, 0);
1092             expect(Ext.encode(ret)).toEqual('[]');
1093         });
1094     });
1095
1096     describe('slice', function(){
1097         
1098         var array;
1099         
1100         describe('with Array', function(){
1101             beforeEach(function(){
1102                 array = [{0:0}, {1:1}, {2:2}, {3:3}];
1103             });
1104             tests();
1105         });
1106         
1107         describe('with arguments', function(){
1108             beforeEach(function(){
1109                 array = (function(){ return arguments; })({0:0}, {1:1}, {2:2}, {3:3});
1110             });
1111             tests();
1112         });
1113         
1114         function tests(){
1115             it('should shallow clone', function(){
1116                 var newArray = Ext.Array.slice(array, 0);
1117                 expect(newArray === array).toBe(false);
1118                 expect(newArray[0] === array[0]).toBe(true);
1119             });
1120             it('should not require a begin or end', function(){
1121                 var newArray = Ext.Array.slice(array);
1122                 expect(newArray === array).toBe(false);
1123                 expect(newArray[0]).toBe(array[0]);
1124             });
1125             it('should slice off the first item', function(){
1126                 var newArray = Ext.Array.slice(array, 1);
1127                 expect(newArray.length).toBe(3);
1128                 expect(newArray[0]).toBe(array[1]);
1129                 expect(newArray[2]).toBe(array[3]);
1130             });
1131             it('should ignore `end` if undefined', function(){
1132                 var newArray = Ext.Array.slice(array, 1, undefined);
1133                 expect(newArray.length).toBe(3);
1134                 expect(newArray[0]).toBe(array[1]);
1135                 expect(newArray[2]).toBe(array[3]);
1136             });
1137             it('should ignore `begin` if undefined', function(){
1138                 var newArray = Ext.Array.slice(array, undefined);
1139                 expect(newArray.length).toBe(4);
1140                 expect(newArray[0]).toBe(array[0]);
1141                 expect(newArray[3]).toBe(array[3]);
1142             });
1143             it('should ignore `begin` and `end` if undefined', function(){
1144                 var newArray = Ext.Array.slice(array, undefined, undefined);
1145                 expect(newArray.length).toBe(4);
1146                 expect(newArray[0]).toBe(array[0]);
1147                 expect(newArray[3]).toBe(array[3]);
1148             });
1149             it('should slice out the middle', function(){
1150                 var newArray = Ext.Array.slice(array, 1, -1);
1151                 expect(newArray.length).toBe(2);
1152                 expect(newArray[0]).toBe(array[1]);
1153                 expect(newArray[1]).toBe(array[2]);
1154             });
1155         }
1156     });
1157 });
1158