Version 1
[yaffs-website] / node_modules / es5-shim / tests / spec / s-array.js
1 /* global describe, it, expect, beforeEach, jasmine, xit */
2
3 var toStr = Object.prototype.toString;
4 var canDistinguishSparseFromUndefined = 0 in [undefined]; // IE 6 - 8 have a bug where this returns false.
5 var ifHasDenseUndefinedsIt = canDistinguishSparseFromUndefined ? it : xit;
6 var undefinedIfNoSparseBug = canDistinguishSparseFromUndefined ? undefined : { valueOf: function () { return 0; } };
7 var hasStrictMode = (function () {
8     'use strict';
9
10     return !this;
11 }());
12 var ifHasStrictIt = hasStrictMode ? it : xit;
13
14 describe('Array', function () {
15     var testSubject;
16
17     beforeEach(function () {
18         testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', null, false, 0];
19         delete testSubject[1];
20     });
21
22     var createArrayLikeFromArray = function createArrayLikeFromArray(arr) {
23         var o = {};
24         Array.prototype.forEach.call(arr, function (e, i) {
25             o[i] = e;
26         });
27         o.length = arr.length;
28         return o;
29     };
30
31     describe('#forEach()', function () {
32         var expected, actual;
33
34         beforeEach(function () {
35             expected = { 0: 2, 2: undefinedIfNoSparseBug, 3: true, 4: 'hej', 5: null, 6: false, 7: 0 };
36             actual = {};
37         });
38
39         it('should pass the right parameters', function () {
40             var callback = jasmine.createSpy('callback');
41             var array = ['1'];
42             array.forEach(callback);
43             expect(callback).toHaveBeenCalledWith('1', 0, array);
44         });
45
46         it('should not affect elements added to the array after it has begun', function () {
47             var arr = [1, 2, 3];
48             var i = 0;
49             arr.forEach(function (a) {
50                 i += 1;
51                 arr.push(a + 3);
52             });
53             expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
54             expect(i).toBe(3);
55         });
56
57         it('should set the right context when given none', function () {
58             var context;
59             [1].forEach(function () { context = this; });
60             expect(context).toBe(function () { return this; }.call());
61         });
62
63         it('should iterate all', function () {
64             testSubject.forEach(function (obj, index) {
65                 actual[index] = obj;
66             });
67             expect(actual).toExactlyMatch(expected);
68         });
69
70         it('should iterate all using a context', function () {
71             var o = { a: actual };
72
73             testSubject.forEach(function (obj, index) {
74                 this.a[index] = obj;
75             }, o);
76             expect(actual).toExactlyMatch(expected);
77         });
78
79         it('should iterate all in an array-like object', function () {
80             var ts = createArrayLikeFromArray(testSubject);
81             Array.prototype.forEach.call(ts, function (obj, index) {
82                 actual[index] = obj;
83             });
84             expect(actual).toExactlyMatch(expected);
85         });
86
87         it('should iterate all in an array-like object using a context', function () {
88             var ts = createArrayLikeFromArray(testSubject);
89             var o = { a: actual };
90
91             Array.prototype.forEach.call(ts, function (obj, index) {
92                 this.a[index] = obj;
93             }, o);
94             expect(actual).toExactlyMatch(expected);
95         });
96
97         describe('strings', function () {
98             var str = 'Hello, World!';
99
100             it('should iterate all in a string', function () {
101                 actual = [];
102                 Array.prototype.forEach.call(str, function (item, index) {
103                     actual[index] = item;
104                 });
105                 expect(actual).toExactlyMatch(str.split(''));
106             });
107
108             it('should iterate all in a string using a context', function () {
109                 actual = [];
110                 var o = { a: actual };
111                 Array.prototype.forEach.call(str, function (item, index) {
112                     this.a[index] = item;
113                 }, o);
114                 expect(actual).toExactlyMatch(str.split(''));
115             });
116         });
117
118         it('should have a boxed object as list argument of callback', function () {
119             var listArg;
120             Array.prototype.forEach.call('foo', function (item, index, list) {
121                 listArg = list;
122             });
123             expect(typeof listArg).toBe('object');
124             expect(toStr.call(listArg)).toBe('[object String]');
125         });
126
127         ifHasStrictIt('does not autobox the content in strict mode', function () {
128             var context;
129             [1].forEach(function () {
130                 'use strict';
131
132                 context = this;
133             }, 'x');
134             expect(typeof context).toBe('string');
135         });
136     });
137     describe('#some()', function () {
138         var actual, expected, numberOfRuns;
139
140         beforeEach(function () {
141             expected = { 0: 2, 2: undefinedIfNoSparseBug, 3: true };
142             actual = {};
143             numberOfRuns = 0;
144         });
145
146         it('should pass the correct values along to the callback', function () {
147             var callback = jasmine.createSpy('callback');
148             var array = ['1'];
149             array.some(callback);
150             expect(callback).toHaveBeenCalledWith('1', 0, array);
151         });
152
153         it('should not affect elements added to the array after it has begun', function () {
154             var arr = [1, 2, 3];
155             var i = 0;
156             arr.some(function (a) {
157                 i += 1;
158                 arr.push(a + 3);
159                 return i > 3;
160             });
161             expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
162             expect(i).toBe(3);
163         });
164
165         it('should set the right context when given none', function () {
166             /* eslint-disable array-callback-return */
167             var context;
168             [1].some(function () { context = this; });
169             expect(context).toBe(function () { return this; }.call());
170         });
171
172         it('should return false if it runs to the end', function () {
173             /* eslint-disable array-callback-return */
174             actual = testSubject.some(function () {});
175             expect(actual).toBeFalsy();
176         });
177
178         it('should return true if it is stopped somewhere', function () {
179             actual = testSubject.some(function () { return true; });
180             expect(actual).toBeTruthy();
181         });
182
183         it('should return false if there are no elements', function () {
184             actual = [].some(function () { return true; });
185             expect(actual).toBeFalsy();
186         });
187
188         it('should stop after 3 elements', function () {
189             testSubject.some(function (obj, index) {
190                 actual[index] = obj;
191                 numberOfRuns += 1;
192                 return numberOfRuns === 3;
193             });
194             expect(actual).toExactlyMatch(expected);
195         });
196
197         it('should stop after 3 elements using a context', function () {
198             var o = { a: actual };
199             testSubject.some(function (obj, index) {
200                 this.a[index] = obj;
201                 numberOfRuns += 1;
202                 return numberOfRuns === 3;
203             }, o);
204             expect(actual).toExactlyMatch(expected);
205         });
206
207         it('should stop after 3 elements in an array-like object', function () {
208             var ts = createArrayLikeFromArray(testSubject);
209             Array.prototype.some.call(ts, function (obj, index) {
210                 actual[index] = obj;
211                 numberOfRuns += 1;
212                 return numberOfRuns === 3;
213             });
214             expect(actual).toExactlyMatch(expected);
215         });
216
217         it('should stop after 3 elements in an array-like object using a context', function () {
218             var ts = createArrayLikeFromArray(testSubject);
219             var o = { a: actual };
220             Array.prototype.some.call(ts, function (obj, index) {
221                 this.a[index] = obj;
222                 numberOfRuns += 1;
223                 return numberOfRuns === 3;
224             }, o);
225             expect(actual).toExactlyMatch(expected);
226         });
227
228         it('should have a boxed object as list argument of callback', function () {
229             var listArg;
230             Array.prototype.some.call('foo', function (item, index, list) {
231                 listArg = list;
232             });
233             expect(typeof listArg).toBe('object');
234             expect(toStr.call(listArg)).toBe('[object String]');
235         });
236     });
237     describe('#every()', function () {
238         var actual, expected, numberOfRuns;
239
240         beforeEach(function () {
241             expected = { 0: 2, 2: undefinedIfNoSparseBug, 3: true };
242             actual = {};
243             numberOfRuns = 0;
244         });
245
246         it('should pass the correct values along to the callback', function () {
247             var callback = jasmine.createSpy('callback');
248             var array = ['1'];
249             array.every(callback);
250             expect(callback).toHaveBeenCalledWith('1', 0, array);
251         });
252
253         it('should not affect elements added to the array after it has begun', function () {
254             var arr = [1, 2, 3];
255             var i = 0;
256             arr.every(function (a) {
257                 i += 1;
258                 arr.push(a + 3);
259                 return i <= 3;
260             });
261             expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
262             expect(i).toBe(3);
263         });
264
265         it('should set the right context when given none', function () {
266             /* eslint-disable array-callback-return */
267             var context;
268             [1].every(function () { context = this; });
269             expect(context).toBe(function () { return this; }.call());
270         });
271
272         it('should return true if the array is empty', function () {
273             actual = [].every(function () { return true; });
274             expect(actual).toBeTruthy();
275
276             actual = [].every(function () { return false; });
277             expect(actual).toBeTruthy();
278         });
279
280         it('should return true if it runs to the end', function () {
281             actual = [1, 2, 3].every(function () { return true; });
282             expect(actual).toBeTruthy();
283         });
284
285         it('should return false if it is stopped before the end', function () {
286             actual = [1, 2, 3].every(function () { return false; });
287             expect(actual).toBeFalsy();
288         });
289
290         it('should return after 3 elements', function () {
291             testSubject.every(function (obj, index) {
292                 actual[index] = obj;
293                 numberOfRuns += 1;
294                 return numberOfRuns !== 3;
295             });
296             expect(actual).toExactlyMatch(expected);
297         });
298
299         it('should stop after 3 elements using a context', function () {
300             var o = { a: actual };
301             testSubject.every(function (obj, index) {
302                 this.a[index] = obj;
303                 numberOfRuns += 1;
304                 return numberOfRuns !== 3;
305             }, o);
306             expect(actual).toExactlyMatch(expected);
307         });
308
309         it('should stop after 3 elements in an array-like object', function () {
310             var ts = createArrayLikeFromArray(testSubject);
311             Array.prototype.every.call(ts, function (obj, index) {
312                 actual[index] = obj;
313                 numberOfRuns += 1;
314                 return numberOfRuns !== 3;
315             });
316             expect(actual).toExactlyMatch(expected);
317         });
318
319         it('should stop after 3 elements in an array-like object using a context', function () {
320             var ts = createArrayLikeFromArray(testSubject);
321             var o = { a: actual };
322             Array.prototype.every.call(ts, function (obj, index) {
323                 this.a[index] = obj;
324                 numberOfRuns += 1;
325                 return numberOfRuns !== 3;
326             }, o);
327             expect(actual).toExactlyMatch(expected);
328         });
329
330         it('should have a boxed object as list argument of callback', function () {
331             var listArg;
332             Array.prototype.every.call('foo', function (item, index, list) {
333                 listArg = list;
334             });
335             expect(typeof listArg).toBe('object');
336             expect(toStr.call(listArg)).toBe('[object String]');
337         });
338     });
339
340     describe('#indexOf()', function () {
341         'use strict';
342
343         var actual, expected;
344
345         beforeEach(function () {
346             testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', null, 2, false, 0];
347             delete testSubject[1];
348         });
349
350         it('should find the element', function () {
351             expected = 4;
352             actual = testSubject.indexOf('hej');
353             expect(actual).toBe(expected);
354         });
355
356         it('should not find the element', function () {
357             expected = -1;
358             actual = testSubject.indexOf('mus');
359             expect(actual).toBe(expected);
360         });
361
362         ifHasDenseUndefinedsIt('should find undefined as well', function () {
363             expected = -1;
364             actual = testSubject.indexOf(undefined);
365             expect(actual).not.toBe(expected);
366         });
367
368         ifHasDenseUndefinedsIt('should skip unset indexes', function () {
369             expected = 2;
370             actual = testSubject.indexOf(undefined);
371             expect(actual).toBe(expected);
372         });
373
374         it('should use a strict test', function () {
375             actual = testSubject.indexOf(null);
376             expect(actual).toBe(5);
377
378             actual = testSubject.indexOf('2');
379             expect(actual).toBe(-1);
380         });
381
382         it('should skip the first if fromIndex is set', function () {
383             expect(testSubject.indexOf(2, 2)).toBe(6);
384             expect(testSubject.indexOf(2, 0)).toBe(0);
385             expect(testSubject.indexOf(2, 6)).toBe(6);
386         });
387
388         it('should work with negative fromIndex', function () {
389             expect(testSubject.indexOf(2, -3)).toBe(6);
390             expect(testSubject.indexOf(2, -9)).toBe(0);
391         });
392
393         it('should work with fromIndex being greater than the length', function () {
394             expect(testSubject.indexOf(0, 20)).toBe(-1);
395         });
396
397         it('should work with fromIndex being negative and greater than the length', function () {
398             expect(testSubject.indexOf('hej', -20)).toBe(4);
399         });
400
401         describe('Array-like', function ArrayLike() {
402             var indexOf = Array.prototype.indexOf;
403             var testAL;
404
405             beforeEach(function beforeEach() {
406                 testAL = {};
407                 testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', null, 2, false, 0];
408                 testSubject.forEach(function (o, i) {
409                     testAL[i] = o;
410                 });
411                 testAL.length = testSubject.length;
412             });
413
414             it('should find the element (array-like)', function () {
415                 expected = 4;
416                 actual = indexOf.call(testAL, 'hej');
417                 expect(actual).toBe(expected);
418             });
419
420             it('should not find the element (array-like)', function () {
421                 expected = -1;
422                 actual = indexOf.call(testAL, 'mus');
423                 expect(actual).toBe(expected);
424             });
425
426             ifHasDenseUndefinedsIt('should find undefined as well (array-like)', function () {
427                 expected = -1;
428                 actual = indexOf.call(testAL, undefined);
429                 expect(actual).not.toBe(expected);
430             });
431
432             ifHasDenseUndefinedsIt('should skip unset indexes (array-like)', function () {
433                 expected = 2;
434                 actual = indexOf.call(testAL, undefined);
435                 expect(actual).toBe(expected);
436             });
437
438             it('should use a strict test (array-like)', function () {
439                 actual = Array.prototype.indexOf.call(testAL, null);
440                 expect(actual).toBe(5);
441
442                 actual = Array.prototype.indexOf.call(testAL, '2');
443                 expect(actual).toBe(-1);
444             });
445
446             it('should skip the first if fromIndex is set (array-like)', function () {
447                 expect(indexOf.call(testAL, 2, 2)).toBe(6);
448                 expect(indexOf.call(testAL, 2, 0)).toBe(0);
449                 expect(indexOf.call(testAL, 2, 6)).toBe(6);
450             });
451
452             it('should work with negative fromIndex (array-like)', function () {
453                 expect(indexOf.call(testAL, 2, -3)).toBe(6);
454                 expect(indexOf.call(testAL, 2, -9)).toBe(0);
455             });
456
457             it('should work with fromIndex being greater than the length (array-like)', function () {
458                 expect(indexOf.call(testAL, 0, 20)).toBe(-1);
459             });
460
461             it('should work with fromIndex being negative and greater than the length (array-like)', function () {
462                 expect(indexOf.call(testAL, 'hej', -20)).toBe(4);
463             });
464         });
465     });
466     describe('#lastIndexOf()', function () {
467         'use strict';
468
469         var actual, expected;
470
471         beforeEach(function () {
472             testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', null, 2, 3, false, 0];
473             delete testSubject[1];
474             delete testSubject[7];
475         });
476
477         describe('Array', function () {
478             it('should find the element', function () {
479                 expected = 4;
480                 actual = testSubject.lastIndexOf('hej');
481                 expect(actual).toBe(expected);
482             });
483
484             it('should not find the element', function () {
485                 expected = -1;
486                 actual = testSubject.lastIndexOf('mus');
487                 expect(actual).toBe(expected);
488             });
489
490             ifHasDenseUndefinedsIt('should find undefined as well', function () {
491                 expected = -1;
492                 actual = testSubject.lastIndexOf(undefined);
493                 expect(actual).not.toBe(expected);
494             });
495
496             ifHasDenseUndefinedsIt('should skip unset indexes', function () {
497                 expected = 2;
498                 actual = testSubject.lastIndexOf(undefined);
499                 expect(actual).toBe(expected);
500             });
501
502             it('should use a strict test', function () {
503                 actual = testSubject.lastIndexOf(null);
504                 expect(actual).toBe(5);
505
506                 actual = testSubject.lastIndexOf('2');
507                 expect(actual).toBe(-1);
508             });
509
510             it('should skip the first if fromIndex is set', function () {
511                 expect(testSubject.lastIndexOf(2, 2)).toBe(0);
512                 expect(testSubject.lastIndexOf(2, 0)).toBe(0);
513                 expect(testSubject.lastIndexOf(2, 6)).toBe(6);
514             });
515
516             it('should work with negative fromIndex', function () {
517                 expect(testSubject.lastIndexOf(2, -3)).toBe(6);
518                 expect(testSubject.lastIndexOf(2, -9)).toBe(0);
519             });
520
521             it('should work with fromIndex being greater than the length', function () {
522                 expect(testSubject.lastIndexOf(2, 20)).toBe(6);
523             });
524
525             it('should work with fromIndex being negative and greater than the length', function () {
526                 expect(testSubject.lastIndexOf(2, -20)).toBe(-1);
527             });
528         });
529
530         describe('Array like', function () {
531             var lastIndexOf = Array.prototype.lastIndexOf;
532             var testAL;
533
534             beforeEach(function () {
535                 testAL = {};
536                 testSubject.forEach(function (o, i) {
537                     testAL[i] = o;
538                 });
539                 testAL.length = testSubject.length;
540             });
541
542             it('should find the element (array-like)', function () {
543                 expected = 4;
544                 actual = lastIndexOf.call(testAL, 'hej');
545                 expect(actual).toBe(expected);
546             });
547
548             it('should not find the element (array-like)', function () {
549                 expected = -1;
550                 actual = lastIndexOf.call(testAL, 'mus');
551                 expect(actual).toBe(expected);
552             });
553
554             ifHasDenseUndefinedsIt('should find undefined as well (array-like)', function () {
555                 expected = -1;
556                 actual = lastIndexOf.call(testAL, undefined);
557                 expect(actual).not.toBe(expected);
558             });
559
560             ifHasDenseUndefinedsIt('should skip unset indexes (array-like)', function () {
561                 expected = 2;
562                 actual = lastIndexOf.call(testAL, undefined);
563                 expect(actual).toBe(expected);
564             });
565
566             it('should use a strict test (array-like)', function () {
567                 actual = lastIndexOf.call(testAL, null);
568                 expect(actual).toBe(5);
569
570                 actual = lastIndexOf.call(testAL, '2');
571                 expect(actual).toBe(-1);
572             });
573
574             it('should skip the first if fromIndex is set', function () {
575                 expect(lastIndexOf.call(testAL, 2, 2)).toBe(0);
576                 expect(lastIndexOf.call(testAL, 2, 0)).toBe(0);
577                 expect(lastIndexOf.call(testAL, 2, 6)).toBe(6);
578             });
579
580             it('should work with negative fromIndex', function () {
581                 expect(lastIndexOf.call(testAL, 2, -3)).toBe(6);
582                 expect(lastIndexOf.call(testAL, 2, -9)).toBe(0);
583             });
584
585             it('should work with fromIndex being greater than the length', function () {
586                 expect(lastIndexOf.call(testAL, 2, 20)).toBe(6);
587             });
588
589             it('should work with fromIndex being negative and greater than the length', function () {
590                 expect(lastIndexOf.call(testAL, 2, -20)).toBe(-1);
591             });
592         });
593     });
594
595     describe('#filter()', function () {
596         var filteredArray;
597         var callback = function callback(o, i) {
598             return i !== 3 && i !== 5;
599         };
600
601         beforeEach(function () {
602             testSubject = [2, 3, undefinedIfNoSparseBug, true, 'hej', 3, null, false, 0];
603             delete testSubject[1];
604             filteredArray = [2, undefinedIfNoSparseBug, 'hej', null, false, 0];
605         });
606         describe('Array object', function () {
607             it('should call the callback with the proper arguments', function () {
608                 var predicate = jasmine.createSpy('predicate');
609                 var arr = ['1'];
610                 arr.filter(predicate);
611                 expect(predicate).toHaveBeenCalledWith('1', 0, arr);
612             });
613
614             it('should not affect elements added to the array after it has begun', function () {
615                 var arr = [1, 2, 3];
616                 var i = 0;
617                 arr.filter(function (a) {
618                     i += 1;
619                     if (i <= 4) {
620                         arr.push(a + 3);
621                     }
622                     return true;
623                 });
624                 expect(arr).toEqual([1, 2, 3, 4, 5, 6]);
625                 expect(i).toBe(3);
626             });
627
628             ifHasDenseUndefinedsIt('should skip unset values', function () {
629                 var passedValues = {};
630                 testSubject = [1, 2, 3, 4];
631                 delete testSubject[1];
632                 testSubject.filter(function (o, i) {
633                     passedValues[i] = o;
634                     return true;
635                 });
636                 expect(passedValues).toExactlyMatch(testSubject);
637             });
638
639             it('should pass the right context to the filter', function () {
640                 var passedValues = {};
641                 testSubject = [1, 2, 3, 4];
642                 delete testSubject[1];
643                 testSubject.filter(function (o, i) {
644                     this[i] = o;
645                     return true;
646                 }, passedValues);
647                 expect(passedValues).toExactlyMatch(testSubject);
648             });
649
650             it('should set the right context when given none', function () {
651                 /* eslint-disable array-callback-return */
652                 var context;
653                 [1].filter(function () { context = this; });
654                 expect(context).toBe(function () { return this; }.call());
655             });
656
657             it('should remove only the values for which the callback returns false', function () {
658                 var result = testSubject.filter(callback);
659                 expect(result).toExactlyMatch(filteredArray);
660             });
661
662             it('should leave the original array untouched', function () {
663                 var copy = testSubject.slice();
664                 testSubject.filter(callback);
665                 expect(testSubject).toExactlyMatch(copy);
666             });
667
668             it('should not be affected by same-index mutation', function () {
669                 var results = [1, 2, 3].filter(function (value, index, array) {
670                     array[index] = 'a';
671                     return true;
672                 });
673                 expect(results).toEqual([1, 2, 3]);
674             });
675         });
676
677         describe('Array like', function () {
678             beforeEach(function () {
679                 testSubject = createArrayLikeFromArray(testSubject);
680             });
681
682             it('should call the predicate with the proper arguments', function () {
683                 var predicate = jasmine.createSpy('predicate');
684                 var arr = createArrayLikeFromArray(['1']);
685                 Array.prototype.filter.call(arr, predicate);
686                 expect(predicate).toHaveBeenCalledWith('1', 0, arr);
687             });
688
689             it('should not affect elements added to the array after it has begun', function () {
690                 var arr = createArrayLikeFromArray([1, 2, 3]);
691                 var i = 0;
692                 Array.prototype.filter.call(arr, function (a) {
693                     i += 1;
694                     if (i <= 4) {
695                         arr[i + 2] = a + 3;
696                         arr.length += 1;
697                     }
698                     return true;
699                 });
700                 expect(Array.prototype.slice.call(arr)).toEqual([1, 2, 3, 4, 5, 6]);
701                 expect(i).toBe(3);
702             });
703
704             it('should skip non-set values', function () {
705                 var passedValues = createArrayLikeFromArray([]);
706                 testSubject = createArrayLikeFromArray([1, 2, 3, 4]);
707                 delete testSubject[1];
708                 Array.prototype.filter.call(testSubject, function (o, i) {
709                     passedValues[i] = o;
710                     passedValues.length = i + 1;
711                     return true;
712                 });
713                 expect(passedValues).toEqual(testSubject);
714             });
715
716             it('should set the right context when given none', function () {
717                 var context;
718                 Array.prototype.filter.call(createArrayLikeFromArray([1]), function () { context = this; }, undefined);
719                 expect(context).toBe(function () { return this; }.call());
720             });
721
722             it('should pass the right context to the filter', function () {
723                 var passedValues = {};
724                 testSubject = createArrayLikeFromArray([1, 2, 3, 4]);
725                 delete testSubject[1];
726                 Array.prototype.filter.call(testSubject, function (o, i) {
727                     this[i] = o;
728                     this.length = i + 1;
729                     return true;
730                 }, passedValues);
731                 expect(passedValues).toEqual(testSubject);
732             });
733
734             it('should remove only the values for which the callback returns false', function () {
735                 var result = Array.prototype.filter.call(testSubject, callback);
736                 expect(result).toExactlyMatch(filteredArray);
737             });
738
739             it('should leave the original array untouched', function () {
740                 var copy = createArrayLikeFromArray(testSubject);
741                 Array.prototype.filter.call(testSubject, callback);
742                 expect(testSubject).toExactlyMatch(copy);
743             });
744         });
745
746         it('should have a boxed object as list argument of callback', function () {
747             var actual;
748             Array.prototype.filter.call('foo', function (item, index, list) {
749                 actual = list;
750             });
751             expect(typeof actual).toBe('object');
752             expect(toStr.call(actual)).toBe('[object String]');
753         });
754     });
755     describe('#map()', function () {
756         var callback;
757         beforeEach(function () {
758             var i = 0;
759             callback = function () {
760                 return i++;
761             };
762         });
763         describe('Array object', function () {
764             it('should call mapper with the right parameters', function () {
765                 var mapper = jasmine.createSpy('mapper');
766                 var array = [1];
767                 array.map(mapper);
768                 expect(mapper).toHaveBeenCalledWith(1, 0, array);
769             });
770
771             it('should set the context correctly', function () {
772                 var context = {};
773                 testSubject.map(function (o, i) {
774                     this[i] = o;
775                 }, context);
776                 expect(context).toExactlyMatch(testSubject);
777             });
778
779             it('should set the right context when given none', function () {
780                 var context;
781                 [1].map(function () { context = this; });
782                 expect(context).toBe(function () { return this; }.call());
783             });
784
785             it('should not change the array it is called on', function () {
786                 var copy = testSubject.slice();
787                 testSubject.map(callback);
788                 expect(testSubject).toExactlyMatch(copy);
789             });
790
791             it('should only run for the number of objects in the array when it started', function () {
792                 var arr = [1, 2, 3];
793                 var i = 0;
794                 arr.map(function (o) {
795                     arr.push(o + 3);
796                     i += 1;
797                     return o;
798                 });
799                 expect(arr).toExactlyMatch([1, 2, 3, 4, 5, 6]);
800                 expect(i).toBe(3);
801             });
802
803             it('should properly translate the values as according to the callback', function () {
804                 var result = testSubject.map(callback);
805                 var expected = [0, 0, 1, 2, 3, 4, 5, 6];
806                 delete expected[1];
807                 expect(result).toExactlyMatch(expected);
808             });
809
810             it('should skip non-existing values', function () {
811                 var array = [1, 2, 3, 4];
812                 var i = 0;
813                 delete array[2];
814                 array.map(function () {
815                     i += 1;
816                 });
817                 expect(i).toBe(3);
818             });
819         });
820         describe('Array-like', function () {
821             beforeEach(function () {
822                 testSubject = createArrayLikeFromArray(testSubject);
823             });
824
825             it('should call mapper with the right parameters', function () {
826                 var mapper = jasmine.createSpy('mapper');
827                 var array = createArrayLikeFromArray([1]);
828                 Array.prototype.map.call(array, mapper);
829                 expect(mapper).toHaveBeenCalledWith(1, 0, array);
830             });
831
832             it('should set the context correctly', function () {
833                 var context = {};
834                 Array.prototype.map.call(testSubject, function (o, i) {
835                     this[i] = o;
836                     this.length = i + 1;
837                 }, context);
838                 expect(context).toEqual(testSubject);
839             });
840
841             it('should set the right context when given none', function () {
842                 var context;
843                 Array.prototype.map.call(createArrayLikeFromArray([1]), function () { context = this; });
844                 expect(context).toBe(function () { return this; }.call());
845             });
846
847             it('should not change the array it is called on', function () {
848                 var copy = createArrayLikeFromArray(testSubject);
849                 Array.prototype.map.call(testSubject, callback);
850                 expect(testSubject).toExactlyMatch(copy);
851             });
852
853             it('should only run for the number of objects in the array when it started', function () {
854                 var arr = createArrayLikeFromArray([1, 2, 3]);
855                 var i = 0;
856                 Array.prototype.map.call(arr, function (o) {
857                     Array.prototype.push.call(arr, o + 3);
858                     i += 1;
859                     return o;
860                 });
861                 expect(Array.prototype.slice.call(arr)).toEqual([1, 2, 3, 4, 5, 6]);
862                 expect(i).toBe(3);
863             });
864
865             it('should properly translate the values as according to the callback', function () {
866                 var result = Array.prototype.map.call(testSubject, callback);
867                 var expected = [0, 0, 1, 2, 3, 4, 5, 6];
868                 delete expected[1];
869                 expect(result).toExactlyMatch(expected);
870             });
871
872             it('should skip non-existing values', function () {
873                 var array = createArrayLikeFromArray([1, 2, 3, 4]);
874                 var i = 0;
875                 delete array[2];
876                 Array.prototype.map.call(array, function () {
877                     i += 1;
878                 });
879                 expect(i).toBe(3);
880             });
881         });
882
883         it('should have a boxed object as list argument of callback', function () {
884             var actual;
885             Array.prototype.map.call('foo', function (item, index, list) {
886                 actual = list;
887             });
888             expect(typeof actual).toBe('object');
889             expect(toStr.call(actual)).toBe('[object String]');
890         });
891     });
892
893     describe('#reduce()', function () {
894         beforeEach(function () {
895             testSubject = [1, 2, 3];
896         });
897
898         describe('Array', function () {
899             it('should pass the correct arguments to the callback', function () {
900                 var spy = jasmine.createSpy().andReturn(0);
901                 testSubject.reduce(spy);
902                 expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);
903             });
904
905             it('should start with the right initialValue', function () {
906                 var spy = jasmine.createSpy().andReturn(0);
907                 testSubject.reduce(spy, 0);
908                 expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);
909             });
910
911             it('should not affect elements added to the array after it has begun', function () {
912                 var arr = [1, 2, 3];
913                 var i = 0;
914                 arr.reduce(function (a, b) {
915                     i += 1;
916                     if (i <= 4) {
917                         arr.push(a + 3);
918                     }
919                     return b;
920                 });
921                 expect(arr).toEqual([1, 2, 3, 4, 5]);
922                 expect(i).toBe(2);
923             });
924
925             it('should work as expected for empty arrays', function () {
926                 var spy = jasmine.createSpy();
927                 expect(function () {
928                     [].reduce(spy);
929                 }).toThrow();
930                 expect(spy).not.toHaveBeenCalled();
931             });
932
933             it('should throw correctly if no callback is given', function () {
934                 expect(function () {
935                     testSubject.reduce();
936                 }).toThrow();
937             });
938
939             it('should return the expected result', function () {
940                 expect(testSubject.reduce(function (a, b) {
941                     return String(a || '') + String(b || '');
942                 })).toBe(testSubject.join(''));
943             });
944
945             it('should not directly affect the passed array', function () {
946                 var copy = testSubject.slice();
947                 testSubject.reduce(function (a, b) {
948                     return a + b;
949                 });
950                 expect(testSubject).toEqual(copy);
951             });
952
953             it('should skip non-set values', function () {
954                 delete testSubject[1];
955                 var visited = {};
956                 testSubject.reduce(function (a, b) {
957                     if (a) { visited[a] = true; }
958                     if (b) { visited[b] = true; }
959                     return 0;
960                 });
961
962                 expect(visited).toEqual({ 1: true, 3: true });
963             });
964
965             it('should have the right length', function () {
966                 expect(testSubject.reduce.length).toBe(1);
967             });
968         });
969         describe('Array-like objects', function () {
970             beforeEach(function () {
971                 testSubject = createArrayLikeFromArray(testSubject);
972                 testSubject.reduce = Array.prototype.reduce;
973             });
974
975             it('should pass the correct arguments to the callback', function () {
976                 var spy = jasmine.createSpy().andReturn(0);
977                 testSubject.reduce(spy);
978                 expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);
979             });
980
981             it('should start with the right initialValue', function () {
982                 var spy = jasmine.createSpy().andReturn(0);
983                 testSubject.reduce(spy, 0);
984                 expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);
985             });
986
987             it('should not affect elements added to the array after it has begun', function () {
988                 var arr = createArrayLikeFromArray([1, 2, 3]);
989                 var i = 0;
990                 Array.prototype.reduce.call(arr, function (a, b) {
991                     i += 1;
992                     if (i <= 4) {
993                         arr[i + 2] = a + 3;
994                     }
995                     return b;
996                 });
997                 expect(arr).toEqual({
998                     0: 1,
999                     1: 2,
1000                     2: 3,
1001                     3: 4,
1002                     4: 5,
1003                     length: 3
1004                 });
1005                 expect(i).toBe(2);
1006             });
1007
1008             it('should work as expected for empty arrays', function () {
1009                 var spy = jasmine.createSpy();
1010                 expect(function () {
1011                     Array.prototype.reduce.call({ length: 0 }, spy);
1012                 }).toThrow();
1013                 expect(spy).not.toHaveBeenCalled();
1014             });
1015
1016             it('should throw correctly if no callback is given', function () {
1017                 expect(function () {
1018                     testSubject.reduce();
1019                 }).toThrow();
1020             });
1021
1022             it('should return the expected result', function () {
1023                 expect(testSubject.reduce(function (a, b) {
1024                     return String(a || '') + String(b || '');
1025                 })).toBe('123');
1026             });
1027
1028             it('should not directly affect the passed array', function () {
1029                 var copy = createArrayLikeFromArray(testSubject);
1030                 testSubject.reduce(function (a, b) {
1031                     return a + b;
1032                 });
1033                 delete testSubject.reduce;
1034                 expect(testSubject).toEqual(copy);
1035             });
1036
1037             it('should skip non-set values', function () {
1038                 delete testSubject[1];
1039                 var visited = {};
1040                 testSubject.reduce(function (a, b) {
1041                     if (a) { visited[a] = true; }
1042                     if (b) { visited[b] = true; }
1043                     return 0;
1044                 });
1045
1046                 expect(visited).toEqual({ 1: true, 3: true });
1047             });
1048
1049             it('should have the right length', function () {
1050                 expect(testSubject.reduce.length).toBe(1);
1051             });
1052         });
1053
1054         it('should have a boxed object as list argument of callback', function () {
1055             var actual;
1056             Array.prototype.reduce.call('foo', function (accumulator, item, index, list) {
1057                 actual = list;
1058             });
1059             expect(typeof actual).toBe('object');
1060             expect(toStr.call(actual)).toBe('[object String]');
1061         });
1062     });
1063     describe('#reduceRight()', function () {
1064         beforeEach(function () {
1065             testSubject = [1, 2, 3];
1066         });
1067
1068         describe('Array', function () {
1069             it('should pass the correct arguments to the callback', function () {
1070                 var spy = jasmine.createSpy().andReturn(0);
1071                 testSubject.reduceRight(spy);
1072                 expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);
1073             });
1074
1075             it('should start with the right initialValue', function () {
1076                 var spy = jasmine.createSpy().andReturn(0);
1077                 testSubject.reduceRight(spy, 0);
1078                 expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);
1079             });
1080
1081             it('should not affect elements added to the array after it has begun', function () {
1082                 var arr = [1, 2, 3];
1083                 var i = 0;
1084                 arr.reduceRight(function (a, b) {
1085                     i += 1;
1086                     if (i <= 4) {
1087                         arr.push(a + 3);
1088                     }
1089                     return b;
1090                 });
1091                 expect(arr).toEqual([1, 2, 3, 6, 5]);
1092                 expect(i).toBe(2);
1093             });
1094
1095             it('should work as expected for empty arrays', function () {
1096                 var spy = jasmine.createSpy();
1097                 expect(function () {
1098                     [].reduceRight(spy);
1099                 }).toThrow();
1100                 expect(spy).not.toHaveBeenCalled();
1101             });
1102
1103             it('should work as expected for empty arrays with an initial value', function () {
1104                 var spy = jasmine.createSpy();
1105                 var result;
1106
1107                 result = [].reduceRight(spy, '');
1108                 expect(spy).not.toHaveBeenCalled();
1109                 expect(result).toBe('');
1110             });
1111
1112             it('should throw correctly if no callback is given', function () {
1113                 expect(function () {
1114                     testSubject.reduceRight();
1115                 }).toThrow();
1116             });
1117
1118             it('should return the expected result', function () {
1119                 expect(testSubject.reduceRight(function (a, b) {
1120                     return String(a || '') + String(b || '');
1121                 })).toBe('321');
1122             });
1123
1124             it('should not directly affect the passed array', function () {
1125                 var copy = testSubject.slice();
1126                 testSubject.reduceRight(function (a, b) {
1127                     return a + b;
1128                 });
1129                 expect(testSubject).toEqual(copy);
1130             });
1131
1132             it('should skip non-set values', function () {
1133                 delete testSubject[1];
1134                 var visited = {};
1135                 testSubject.reduceRight(function (a, b) {
1136                     if (a) { visited[a] = true; }
1137                     if (b) { visited[b] = true; }
1138                     return 0;
1139                 });
1140
1141                 expect(visited).toEqual({ 1: true, 3: true });
1142             });
1143
1144             it('should have the right length', function () {
1145                 expect(testSubject.reduceRight.length).toBe(1);
1146             });
1147         });
1148         describe('Array-like objects', function () {
1149             beforeEach(function () {
1150                 testSubject = createArrayLikeFromArray(testSubject);
1151                 testSubject.reduceRight = Array.prototype.reduceRight;
1152             });
1153
1154             it('should pass the correct arguments to the callback', function () {
1155                 var spy = jasmine.createSpy().andReturn(0);
1156                 testSubject.reduceRight(spy);
1157                 expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);
1158             });
1159
1160             it('should start with the right initialValue', function () {
1161                 var spy = jasmine.createSpy().andReturn(0);
1162                 testSubject.reduceRight(spy, 0);
1163                 expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);
1164             });
1165
1166             it('should not affect elements added to the array after it has begun', function () {
1167                 var arr = createArrayLikeFromArray([1, 2, 3]);
1168                 var i = 0;
1169                 Array.prototype.reduceRight.call(arr, function (a, b) {
1170                     i += 1;
1171                     if (i <= 4) {
1172                         arr[i + 2] = a + 3;
1173                     }
1174                     return b;
1175                 });
1176                 expect(arr).toEqual({
1177                     0: 1,
1178                     1: 2,
1179                     2: 3,
1180                     3: 6,
1181                     4: 5,
1182                     length: 3 // does not get updated on property assignment
1183                 });
1184                 expect(i).toBe(2);
1185             });
1186
1187             it('should work as expected for empty arrays', function () {
1188                 var spy = jasmine.createSpy();
1189                 expect(function () {
1190                     Array.prototype.reduceRight.call({ length: 0 }, spy);
1191                 }).toThrow();
1192                 expect(spy).not.toHaveBeenCalled();
1193             });
1194
1195             it('should throw correctly if no callback is given', function () {
1196                 expect(function () {
1197                     testSubject.reduceRight();
1198                 }).toThrow();
1199             });
1200
1201             it('should return the expected result', function () {
1202                 expect(testSubject.reduceRight(function (a, b) {
1203                     return String(a || '') + String(b || '');
1204                 })).toBe('321');
1205             });
1206
1207             it('should not directly affect the passed array', function () {
1208                 var copy = createArrayLikeFromArray(testSubject);
1209                 testSubject.reduceRight(function (a, b) {
1210                     return a + b;
1211                 });
1212                 delete testSubject.reduceRight;
1213                 expect(testSubject).toEqual(copy);
1214             });
1215
1216             it('should skip non-set values', function () {
1217                 delete testSubject[1];
1218                 var visited = {};
1219                 testSubject.reduceRight(function (a, b) {
1220                     if (a) { visited[a] = true; }
1221                     if (b) { visited[b] = true; }
1222                     return 0;
1223                 });
1224
1225                 expect(visited).toEqual({ 1: true, 3: true });
1226             });
1227
1228             it('should have the right length', function () {
1229                 expect(testSubject.reduceRight.length).toBe(1);
1230             });
1231         });
1232
1233         it('should have a boxed object as list argument of callback', function () {
1234             var actual;
1235             Array.prototype.reduceRight.call('foo', function (accumulator, item, index, list) {
1236                 actual = list;
1237             });
1238             expect(typeof actual).toBe('object');
1239             expect(toStr.call(actual)).toBe('[object String]');
1240         });
1241     });
1242
1243     describe('.isArray()', function () {
1244         it('should be true for Array', function () {
1245             expect(Array.isArray([])).toBe(true);
1246         });
1247
1248         it('should be false for primitives', function () {
1249             var primitives = [
1250                 'foo',
1251                 true,
1252                 false,
1253                 42,
1254                 0,
1255                 -0,
1256                 NaN,
1257                 Infinity,
1258                 -Infinity
1259             ];
1260             primitives.forEach(function (v) {
1261                 expect(Array.isArray(v)).toBe(false);
1262             });
1263         });
1264
1265         it('should fail for other objects', function () {
1266             var objects = [
1267                 {},
1268                 /foo/,
1269                 arguments
1270             ];
1271             if (Object.create) {
1272                 objects.push(Object.create(null));
1273             }
1274
1275             objects.forEach(function (v) {
1276                 expect(Array.isArray(v)).toBe(false);
1277             });
1278         });
1279
1280         /* globals document */
1281         if (typeof document !== 'undefined') {
1282             it('should be false for an HTML element', function () {
1283                 var el = document.getElementsByTagName('div');
1284                 expect(Array.isArray(el)).toBe(false);
1285             });
1286         }
1287     });
1288
1289     describe('#shift()', function () {
1290         it('works on arrays', function () {
1291             var arr = [1, 2];
1292             var result = arr.shift();
1293             expect(result).toBe(1);
1294             expect(arr.length).toBe(1);
1295             expect(Object.prototype.hasOwnProperty.call(arr, 0)).toBe(true);
1296             expect(Object.prototype.hasOwnProperty.call(arr, 1)).toBe(false);
1297             expect(arr[0]).toBe(2);
1298             expect(arr[1]).toBeUndefined();
1299         });
1300
1301         it('is generic', function () {
1302             var obj = { 0: 1, 1: 2, length: 2 };
1303             var result = Array.prototype.shift.call(obj);
1304             expect(result).toBe(1);
1305             expect(obj.length).toBe(1);
1306             expect(Object.prototype.hasOwnProperty.call(obj, 0)).toBe(true);
1307             expect(Object.prototype.hasOwnProperty.call(obj, 1)).toBe(false);
1308             expect(obj[0]).toBe(2);
1309             expect(obj[1]).toBeUndefined();
1310         });
1311     });
1312
1313     describe('#unshift()', function () {
1314         it('should return length', function () {
1315             expect([].unshift(0)).toBe(1);
1316         });
1317
1318         it('works on arrays', function () {
1319             var arr = [1];
1320             var result = arr.unshift(undefined);
1321             expect(result).toBe(2);
1322             expect(arr.length).toBe(2);
1323             expect(Object.prototype.hasOwnProperty.call(arr, 0)).toBe(true);
1324             expect(Object.prototype.hasOwnProperty.call(arr, 1)).toBe(true);
1325             expect(arr[0]).toBeUndefined();
1326             expect(arr[1]).toBe(1);
1327         });
1328
1329         it('is generic', function () {
1330             var obj = { 0: 1, length: 1 };
1331             var result = Array.prototype.unshift.call(obj, undefined);
1332             expect(result).toBe(2);
1333             expect(obj.length).toBe(2);
1334             expect(Object.prototype.hasOwnProperty.call(obj, 0)).toBe(true);
1335             expect(Object.prototype.hasOwnProperty.call(obj, 1)).toBe(true);
1336             expect(obj[0]).toBeUndefined();
1337             expect(obj[1]).toBe(1);
1338         });
1339     });
1340
1341     describe('#splice()', function () {
1342         var b = ['b'];
1343         var a = [1, 'a', b];
1344         var test;
1345
1346         var makeArray = function (l, givenPrefix) {
1347             var prefix = givenPrefix || '';
1348             var length = l;
1349             var arr = [];
1350             while (length--) {
1351                 arr.unshift(prefix + Array(length + 1).join(' ') + length);
1352             }
1353             return arr;
1354         };
1355
1356         beforeEach(function () {
1357             test = a.slice(0);
1358         });
1359
1360         it('has the right length', function () {
1361             expect(Array.prototype.splice.length).toBe(2);
1362         });
1363
1364         /* This test is disabled, because ES6 normalizes actual
1365          * browser behavior, contradicting ES5.
1366          */
1367         xit('treats undefined deleteCount as 0', function () {
1368             expect(test.splice(0).length).toBe(0);
1369             expect(test.splice(0)).toEqual(test.splice(0, 0));
1370         });
1371
1372         it('basic implementation test 1', function () {
1373             expect(test.splice(0, 0)).toEqual([]);
1374         });
1375
1376         it('basic implementation test 2', function () {
1377             test.splice(0, 2);
1378             expect(test).toEqual([b]);
1379         });
1380
1381         it('should return right result 1', function () {
1382             var array = [];
1383
1384             array.splice(0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
1385             array.splice(1, 0, 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24', 'F25', 'F26');
1386             array.splice(5, 0, 'XXX');
1387
1388             expect(array).toEqual([1, 'F1', 'F2', 'F3', 'F4', 'XXX', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24', 'F25', 'F26', 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
1389         });
1390
1391         it('should return right result 2', function () {
1392             var array = makeArray(6);
1393
1394             array.splice(array.length - 1, 1, '');
1395             array.splice(0, 1, 1, 2, 3, 4);
1396             array.splice(0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45);
1397
1398             array.splice(4, 0, '99999999999999');
1399
1400             expect(array).toEqual([1, 2, 3, 4, '99999999999999', 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 1, 2, 3, 4, ' 1', '  2', '   3', '    4', '']);
1401         });
1402
1403         it('should return right result 3', function () {
1404             var array = [1, 2, 3];
1405
1406             array.splice(0, array.length);
1407             array.splice(0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1408             array.splice(1, 1, 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24', 'F25', 'F26');
1409             array.splice(5, 1, 'YYY', 'XXX');
1410             array.splice(0, 1);
1411             array.splice(0, 2);
1412             array.pop();
1413             array.push.apply(array, makeArray(10, '-'));
1414             array.splice(array.length - 2, 10);
1415             array.splice();
1416             array.splice(1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9);
1417             array.splice(1, 1, 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24', 'F25', 'F26', 1, 23, 4, 5, 6, 7, 8);
1418             array.splice(30, 10);
1419             array.splice(30, 1);
1420             array.splice(30, 0);
1421             array.splice(2, 5, 1, 2, 3, 'P', 'LLL', 'CCC', 'YYY', 'XXX');
1422             array.push(1, 2, 3, 4, 5, 6);
1423             array.splice(1, 6, 1, 2, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9);
1424             array.splice(3, 7);
1425             array.unshift(7, 8, 9, 10, 11);
1426             array.pop();
1427             array.splice(5, 2);
1428             array.pop();
1429             array.unshift.apply(array, makeArray(8, '~'));
1430             array.pop();
1431             array.splice(3, 1, 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24', 'F25', 'F26', 1, 23, 4, 5, 6, 7, 8);
1432             array.splice(4, 5, 'P', 'LLL', 'CCC', 'YYY', 'XXX');
1433
1434             expect(array).toEqual(['~0', '~ 1', '~  2', 'F1', 'P', 'LLL', 'CCC', 'YYY', 'XXX', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24', 'F25', 'F26', 1, 23, 4, 5, 6, 7, 8, '~    4', '~     5', '~      6', '~       7', 7, 8, 9, 10, 11, 2, 4, 5, 6, 7, 8, 9, 'CCC', 'YYY', 'XXX', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24', 'F25', 'F26', 1, 23, 4, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'YYY', 'XXX', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24', 'F25', 'F26', 3, 4, 5, 6, 7, 8, 9, '-0', '- 1', '-  2', '-   3', '-    4', '-     5', '-      6', '-       7', 1, 2, 3]);
1435         });
1436
1437         it('should do nothing if method called with no arguments', function () {
1438             expect(test.splice()).toEqual([]);
1439             expect(test).toEqual(a);
1440         });
1441
1442         it('should set first argument to 0 if first argument is set but undefined', function () {
1443             var test2 = test.slice(0);
1444             expect(test.splice(void 0, 2)).toEqual(test2.splice(0, 2));
1445             expect(test).toEqual(test2);
1446         });
1447
1448         it('should work with objects - adding 1', function () {
1449             var obj = {};
1450             Array.prototype.splice.call(obj, 0, 0, 1, 2, 3);
1451             expect(obj.length).toBe(3);
1452         });
1453
1454         it('should work with objects - adding 2', function () {
1455             var obj = { 0: 1, length: 1 };
1456             Array.prototype.splice.call(obj, 1, 0, 2, 3);
1457             expect(obj.length).toBe(3);
1458         });
1459
1460         it('should work with objects - removing', function () {
1461             var obj = { 0: 1, 1: 2, 2: 3, length: 3 };
1462             Array.prototype.splice.call(obj, 0, 3);
1463             expect(obj.length).toBe(0);
1464         });
1465
1466         it('should work with objects - replacing', function () {
1467             var obj = { 0: 99, length: 1 };
1468             Array.prototype.splice.call(obj, 0, 1, 1, 2, 3);
1469             expect(obj.length).toBe(3);
1470             expect(obj[0]).toBe(1);
1471         });
1472
1473         ifHasDenseUndefinedsIt('should not break on sparse arrays in Opera', function () {
1474             // test from https://github.com/wikimedia/VisualEditor/blob/d468b00311e69c2095b9da360c5745153342a5c3/src/ve.utils.js#L182-L196
1475             var n = 256;
1476             var arr = [];
1477             arr[n] = 'a';
1478             arr.splice(n + 1, 0, 'b');
1479             expect(arr[n]).toBe('a');
1480         });
1481
1482         ifHasDenseUndefinedsIt('should not break on sparse arrays in Safari 7/8', function () {
1483             // test from https://github.com/wikimedia/VisualEditor/blob/d468b00311e69c2095b9da360c5745153342a5c3/src/ve.utils.js#L182-L196
1484             var justFine = new Array(1e5 - 1);
1485             justFine[10] = 'x';
1486             var tooBig = new Array(1e5);
1487             tooBig[8] = 'x';
1488
1489             justFine.splice(1, 1);
1490             expect(8 in justFine).toBe(false);
1491             expect(justFine.indexOf('x')).toBe(9);
1492             tooBig.splice(1, 1);
1493             expect(6 in tooBig).toBe(false);
1494             expect(tooBig.indexOf('x')).toBe(7);
1495         });
1496     });
1497
1498     describe('#join()', function () {
1499         it('defaults to a comma separator when none is provided', function () {
1500             expect([1, 2].join()).toBe('1,2');
1501         });
1502
1503         it('defaults to a comma separator when undefined is provided', function () {
1504             expect([1, 2].join(undefined)).toBe('1,2');
1505         });
1506
1507         it('works, extended', function () {
1508             expect([].join()).toBe('');
1509             expect([undefined].join()).toBe('');
1510             expect([undefined, undefined].join()).toBe(',');
1511             expect([null, null].join()).toBe(',');
1512             expect([undefined, undefined].join('|')).toBe('|');
1513             expect([null, null].join('|')).toBe('|');
1514             expect([1, 2, 3].join('|')).toBe('1|2|3');
1515             expect([1, 2, 3].join(null)).toBe('1null2null3');
1516             expect([1, 2, 3].join({})).toBe('1[object Object]2[object Object]3');
1517             expect([1, 2, 3].join('')).toBe('123');
1518         });
1519
1520         it('is generic', function () {
1521             var obj = { 0: 1, 1: 2, 2: 3, 3: 4, length: 3 };
1522             expect(Array.prototype.join.call(obj, ',')).toBe('1,2,3');
1523         });
1524
1525         it('works with a string literal', function () {
1526             var str = '123';
1527             expect(Array.prototype.join.call(str, ',')).toBe('1,2,3');
1528         });
1529
1530         it('works with `arguments`', function () {
1531             var args = (function () { return arguments; }(1, 2, 3));
1532             expect(Array.prototype.join.call(args, ',')).toBe('1,2,3');
1533         });
1534     });
1535
1536     describe('#push()', function () {
1537         it('works on arrays', function () {
1538             var arr = [];
1539             var result = arr.push(undefined);
1540             expect(result).toBe(1);
1541             expect(arr.length).toBe(1);
1542             expect(Object.prototype.hasOwnProperty.call(arr, 0)).toBe(true);
1543             expect(arr[0]).toBeUndefined();
1544         });
1545
1546         it('is generic', function () {
1547             var obj = {};
1548             var result = Array.prototype.push.call(obj, undefined);
1549             expect(result).toBe(1);
1550             expect(obj.length).toBe(1);
1551             expect(Object.prototype.hasOwnProperty.call(obj, 0)).toBe(true);
1552             expect(obj[0]).toBeUndefined();
1553         });
1554     });
1555
1556     describe('#pop()', function () {
1557         it('works on arrays', function () {
1558             var arr = [1, 2, 3];
1559             var result = arr.pop();
1560             expect(result).toBe(3);
1561             expect(arr.length).toBe(2);
1562             expect(Object.prototype.hasOwnProperty.call(arr, 2)).toBe(false);
1563             expect(arr[2]).toBeUndefined();
1564         });
1565
1566         it('is generic', function () {
1567             var obj = { 0: 1, 1: 2, 2: 3, length: 3 };
1568             var result = Array.prototype.pop.call(obj);
1569             expect(result).toBe(3);
1570             expect(obj.length).toBe(2);
1571             expect(Object.prototype.hasOwnProperty.call(obj, 2)).toBe(false);
1572             expect(obj[2]).toBeUndefined();
1573         });
1574     });
1575
1576     describe('#slice()', function () {
1577         it('works on arrays', function () {
1578             var arr = [1, 2, 3, 4];
1579             var result = arr.slice(1, 3);
1580             expect(result).toEqual([2, 3]);
1581         });
1582
1583         it('is generic', function () {
1584             var obj = { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 };
1585             var result = Array.prototype.slice.call(obj, 1, 3);
1586             expect(result).toEqual([2, 3]);
1587         });
1588
1589         it('works with `arguments`', function () {
1590             var obj = (function () {
1591                 return arguments;
1592             }(1, 2, 3, 4));
1593             var result = Array.prototype.slice.call(obj, 1, 3);
1594             expect(result).toEqual([2, 3]);
1595         });
1596
1597         it('boxed string access', function () {
1598             var obj = '1234';
1599             var result = Array.prototype.slice.call(obj, 1, 3);
1600             expect(result).toEqual(['2', '3']);
1601         });
1602     });
1603
1604     describe('#sort()', function () {
1605         describe('usage', function () {
1606             it('requires a function or undefined as first argument', function () {
1607                 var actual = [1, 2];
1608                 expect(actual.sort()).toBe(actual);
1609                 expect(actual.sort(undefined)).toBe(actual);
1610                 expect(actual.sort(function () { return 0; })).toBe(actual);
1611             });
1612
1613             it('requires a non-function or non-undefined to throw a `TypeError`', function () {
1614                 expect(function () { [1, 2].sort(null); }).toThrow();
1615                 expect(function () { [1, 2].sort(1); }).toThrow();
1616                 expect(function () { [1, 2].sort(''); }).toThrow();
1617                 expect(function () { [1, 2].sort(true); }).toThrow();
1618                 expect(function () { [1, 2].sort({}); }).toThrow();
1619                 expect(function () { [1, 2].sort([]); }).toThrow();
1620                 expect(function () { [1, 2].sort(new Date()); }).toThrow();
1621                 expect(function () { [1, 2].sort(/pattern/); }).toThrow();
1622             });
1623         });
1624
1625         describe('ascending', function () {
1626             it('[5,2,4,6,1,3] should result in [1,2,3,4,5,6]', function () {
1627                 var actual = [5, 2, 4, 6, 1, 3];
1628                 var expected = [1, 2, 3, 4, 5, 6];
1629                 actual.sort();
1630                 expect(actual).toEqual(expected);
1631             });
1632
1633             it('[5,2,2,6,1,3] should result in [1,2,2,3,5,6]', function () {
1634                 var actual = [5, 2, 2, 6, 1, 3];
1635                 var expected = [1, 2, 2, 3, 5, 6];
1636                 actual.sort();
1637                 expect(actual).toEqual(expected);
1638             });
1639
1640             it('[0,0,0,0,0,1] should result in [0,0,0,0,0,1]', function () {
1641                 var actual = [0, 0, 0, 0, 0, 1];
1642                 var expected = [0, 0, 0, 0, 0, 1];
1643                 actual.sort();
1644                 expect(actual).toEqual(expected);
1645             });
1646
1647             it('[0,0,0,0,0,-1] should result in [-1,0,0,0,0,0]', function () {
1648                 var actual = [0, 0, 0, 0, 0, -1];
1649                 var expected = [-1, 0, 0, 0, 0, 0];
1650                 actual.sort();
1651                 expect(actual).toEqual(expected);
1652             });
1653
1654             it('[f,e,d,a,c,b] should result in [a,b,c,d,e,f]', function () {
1655                 var actual = ['f', 'e', 'd', 'a', 'c', 'b'];
1656                 var expected = ['a', 'b', 'c', 'd', 'e', 'f'];
1657                 actual.sort();
1658                 expect(actual).toEqual(expected);
1659             });
1660
1661             it('[f,e,d,,,,a,c,b] should result in [a,b,c,d,e,f,,,]', function () {
1662                 var actual = ['f', 'e', 'd', 1, 2, 'a', 'c', 'b'];
1663                 delete actual[3];
1664                 delete actual[4];
1665                 var expected = ['a', 'b', 'c', 'd', 'e', 'f'];
1666                 expected.length = 8;
1667                 actual.sort();
1668                 expect(actual).toEqual(expected);
1669             });
1670
1671             it('[f,e,d,,null,,a,c,b] should result in [a,b,c,d,e,f,null,,,]', function () {
1672                 var actual = ['f', 'e', 'd', 1, null, 2, 'a', 'c', 'b'];
1673                 delete actual[3];
1674                 delete actual[5];
1675                 var expected = ['a', 'b', 'c', 'd', 'e', 'f', null];
1676                 expected.length = 9;
1677                 actual.sort();
1678                 expect(actual).toEqual(expected);
1679             });
1680
1681             it('[f,e,d,,null,undefined,a,c,b] should result in [a,b,c,d,e,f,null,undefined,,]', function () {
1682                 var actual = ['f', 'e', 'd', 1, null, undefined, 'a', 'c', 'b'];
1683                 delete actual[3];
1684                 var expected = ['a', 'b', 'c', 'd', 'e', 'f', null, undefined];
1685                 expected.length = 9;
1686                 actual.sort();
1687                 expect(actual).toEqual(expected);
1688             });
1689
1690             it('[] should result in []', function () {
1691                 var actual = [];
1692                 var expected = [];
1693                 actual.sort();
1694                 expect(actual).toEqual(expected);
1695             });
1696
1697             it('[1] should result in [1]', function () {
1698                 var actual = [1];
1699                 var expected = [1];
1700                 actual.sort();
1701                 expect(actual).toEqual(expected);
1702             });
1703
1704             it('result should find only greater or equal values', function () {
1705                 var actual = [];
1706                 var i;
1707                 for (i = 0; i < 100; i += 1) {
1708                     actual.push(('00' + (Math.random() * 100).toFixed(0)).slice(-3));
1709                 }
1710                 actual.sort();
1711                 for (i = 0; i < actual.length - 1; i += 1) {
1712                     expect(actual[i] <= actual[i + 1]).toBe(true);
1713                 }
1714             });
1715         });
1716
1717         describe('descending', function () {
1718             var descending = function (left, right) {
1719                 var leftS = String(left);
1720                 var rightS = String(right);
1721                 if (leftS === rightS) {
1722                     return +0;
1723                 }
1724                 if (leftS < rightS) {
1725                     return 1;
1726                 }
1727                 return -1;
1728             };
1729
1730             it('[5,2,4,6,1,3] should result in [6,5,4,3,2,1]', function () {
1731                 var actual = [5, 2, 4, 6, 1, 3];
1732                 var expected = [6, 5, 4, 3, 2, 1];
1733                 actual.sort(descending);
1734                 expect(actual).toEqual(expected);
1735             });
1736
1737             it('[5,2,2,6,1,3] should result in [6,5,4,2,2,1]', function () {
1738                 var actual = [5, 2, 2, 6, 1, 3];
1739                 var expected = [6, 5, 3, 2, 2, 1];
1740                 actual.sort(descending);
1741                 expect(actual).toEqual(expected);
1742             });
1743
1744             it('[0,0,0,0,0,1] should result in [1,0,0,0,0,0]', function () {
1745                 var actual = [0, 0, 0, 0, 0, 1];
1746                 var expected = [1, 0, 0, 0, 0, 0];
1747                 actual.sort(descending);
1748                 expect(actual).toEqual(expected);
1749             });
1750
1751             it('[0,0,0,0,0,-1] should result in [0,0,0,0,0,-1]', function () {
1752                 var actual = [0, 0, 0, 0, 0, -1];
1753                 var expected = [0, 0, 0, 0, 0, -1];
1754                 actual.sort(descending);
1755                 expect(actual).toEqual(expected);
1756             });
1757
1758             it('[f,e,d,a,c,b] should result in [f,e,d,c,b,a]', function () {
1759                 var actual = ['f', 'e', 'd', 'a', 'c', 'b'];
1760                 var expected = ['f', 'e', 'd', 'c', 'b', 'a'];
1761                 actual.sort(descending);
1762                 expect(actual).toEqual(expected);
1763             });
1764
1765             it('[f,e,d,,,a,c,b] should result in [f,e,d,c,b,a,,,]', function () {
1766                 var actual = ['f', 'e', 'd', 1, 2, 'a', 'c', 'b'];
1767                 delete actual[3];
1768                 delete actual[4];
1769                 var expected = ['f', 'e', 'd', 'c', 'b', 'a'];
1770                 expected.length = 8;
1771                 actual.sort(descending);
1772                 expect(actual).toEqual(expected);
1773             });
1774
1775             it('[f,e,d,,null,,a,c,b] should result in [null,f,e,d,c,b,a,,,]', function () {
1776                 var actual = ['f', 'e', 'd', 1, null, 2, 'a', 'c', 'b'];
1777                 delete actual[3];
1778                 delete actual[5];
1779                 var expected = [null, 'f', 'e', 'd', 'c', 'b', 'a'];
1780                 expected.length = 9;
1781                 actual.sort(descending);
1782                 expect(actual).toEqual(expected);
1783             });
1784
1785             it('[f,e,d,undefined,null,,a,c,b] should result in [null,f,e,d,c,b,a,undefined,,]', function () {
1786                 var actual = ['f', 'e', 'd', undefined, null, 2, 'a', 'c', 'b'];
1787                 delete actual[5];
1788                 var expected = [null, 'f', 'e', 'd', 'c', 'b', 'a', undefined];
1789                 expected.length = 9;
1790                 actual.sort(descending);
1791                 expect(actual).toEqual(expected);
1792             });
1793
1794             it('[] should result in []', function () {
1795                 var actual = [];
1796                 var expected = [];
1797                 actual.sort(descending);
1798                 expect(actual).toEqual(expected);
1799             });
1800
1801             it('[1] should result in [1]', function () {
1802                 var actual = [1];
1803                 var expected = [1];
1804                 actual.sort(descending);
1805                 expect(actual).toEqual(expected);
1806             });
1807
1808             it('result should find only lesser or equal values', function () {
1809                 var actual = [];
1810                 var i;
1811                 for (i = 0; i < 100; i += 1) {
1812                     actual.push(('00' + (Math.random() * 100).toFixed(0)).slice(-3));
1813                 }
1814                 actual.sort(descending);
1815                 for (i = 0; i < actual.length - 1; i += 1) {
1816                     expect(actual[i] >= actual[i + 1]).toBe(true);
1817                 }
1818             });
1819         });
1820
1821         describe('returned value', function () {
1822             it('should be the source object', function () {
1823                 var actual = [1, 3, 2];
1824                 expect(actual.sort()).toBe(actual);
1825             });
1826         });
1827
1828         describe('when used generically', function () {
1829             var descending = function (left, right) {
1830                 var leftS = String(left);
1831                 var rightS = String(right);
1832                 if (leftS === rightS) {
1833                     return +0;
1834                 }
1835                 if (leftS < rightS) {
1836                     return 1;
1837                 }
1838                 return -1;
1839             };
1840
1841             var args = function () {
1842                 return arguments;
1843             };
1844
1845             it('should not sort objects without length', function () {
1846                 var actual = {
1847                     0: 5,
1848                     1: 2,
1849                     2: 4,
1850                     3: 6,
1851                     4: 1,
1852                     5: 3
1853                 };
1854                 var expected = {
1855                     0: 5,
1856                     1: 2,
1857                     2: 4,
1858                     3: 6,
1859                     4: 1,
1860                     5: 3
1861                 };
1862                 Array.prototype.sort.call(actual);
1863                 expect(actual).toEqual(expected);
1864                 Array.prototype.sort.call(actual, descending);
1865                 expect(actual).toEqual(expected);
1866             });
1867
1868             it('should sort objects ascending with length', function () {
1869                 var actual = {
1870                     0: 5,
1871                     1: 2,
1872                     2: 4,
1873                     3: 6,
1874                     4: 1,
1875                     5: 3,
1876                     length: 6
1877                 };
1878                 var expected = {
1879                     0: 1,
1880                     1: 2,
1881                     2: 3,
1882                     3: 4,
1883                     4: 5,
1884                     5: 6,
1885                     length: 6
1886                 };
1887                 Array.prototype.sort.call(actual);
1888                 expect(actual).toEqual(expected);
1889             });
1890
1891             it('should sort objects descending with length', function () {
1892                 var actual = {
1893                     0: 5,
1894                     1: 2,
1895                     2: 4,
1896                     3: 6,
1897                     4: 1,
1898                     5: 3,
1899                     length: 6
1900                 };
1901                 var expected = {
1902                     0: 6,
1903                     1: 5,
1904                     2: 4,
1905                     3: 3,
1906                     4: 2,
1907                     5: 1,
1908                     length: 6
1909                 };
1910                 Array.prototype.sort.call(actual, descending);
1911                 expect(actual).toEqual(expected);
1912             });
1913
1914             it('should sort objects descending with mixed content types and with length', function () {
1915                 var actual = {
1916                     0: 5,
1917                     1: 2,
1918                     2: 4,
1919                     4: null,
1920                     6: 1,
1921                     7: 3,
1922                     length: 8
1923                 };
1924                 var expected = {
1925                     0: null,
1926                     1: 5,
1927                     2: 4,
1928                     3: 3,
1929                     4: 2,
1930                     5: 1,
1931                     length: 8
1932                 };
1933                 Array.prototype.sort.call(actual, descending);
1934                 expect(actual).toEqual(expected);
1935             });
1936
1937             it('should sort `arguments` object ascending', function () {
1938                 var actual = args(5, 2, 4, 6, 1, 3);
1939                 var expected = args(1, 2, 3, 4, 5, 6);
1940                 Array.prototype.sort.call(actual);
1941                 expect(actual).toEqual(expected);
1942             });
1943
1944             it('should sort `arguments` object ascending with mixed content types', function () {
1945                 var actual = args(5, 2, 4, null, 1, 3);
1946                 var expected = args(1, 2, 3, 4, 5, null);
1947                 Array.prototype.sort.call(actual);
1948                 expect(actual).toEqual(expected);
1949             });
1950
1951             it('should sort `arguments` object descending', function () {
1952                 var actual = args(5, 2, 4, 6, 1, 3);
1953                 var expected = args(6, 5, 4, 3, 2, 1);
1954                 Array.prototype.sort.call(actual, descending);
1955                 expect(actual).toEqual(expected);
1956             });
1957
1958             it('should sort `arguments` object descending with mixed content types', function () {
1959                 var actual = args(5, 2, 4, null, 1, 3);
1960                 var expected = args(null, 5, 4, 3, 2, 1);
1961                 Array.prototype.sort.call(actual, descending);
1962                 expect(actual).toEqual(expected);
1963             });
1964         });
1965     });
1966 });