PageRenderTime 2561ms CodeModel.GetById 833ms app.highlight 1226ms RepoModel.GetById 473ms app.codeStats 1ms

/tests/spec/s-array.js

https://github.com/milk012/es5-shim
JavaScript | 1144 lines | 1092 code | 51 blank | 1 comment | 60 complexity | 4f62753571ba06fbb58dde2db8e10625 MD5 | raw file
   1describe('Array', function() {
   2    var testSubject;
   3    beforeEach(function() {
   4        testSubject = [2, 3, undefined, true, 'hej', null, false, 0];
   5        delete testSubject[1];
   6    });
   7    function createArrayLikeFromArray(arr) {
   8        var o = {};
   9        Array.prototype.forEach.call(arr, function(e, i) {
  10            o[i]=e;
  11        });
  12        o.length = arr.length;
  13        return o;
  14    };
  15    
  16    describe('forEach', function() {
  17        "use strict";
  18        var expected, actual;
  19        
  20        beforeEach(function() {
  21            expected = {0:2, 2: undefined, 3:true, 4: 'hej', 5:null, 6:false, 7:0 };
  22            actual = {};
  23        });
  24        it('should pass the right parameters', function() {
  25            var callback = jasmine.createSpy('callback'),
  26                array = ['1'];
  27            array.forEach(callback);
  28            expect(callback).toHaveBeenCalledWith('1', 0, array);
  29        });
  30        it('should not affect elements added to the array after it has begun', function() {
  31            var arr = [1,2,3],
  32                i = 0;
  33            arr.forEach(function(a) {
  34                i++;
  35                arr.push(a+3);
  36            });
  37            expect(arr).toEqual([1,2,3,4,5,6]);
  38            expect(i).toBe(3);
  39        });
  40        
  41        it('should set the right context when given none', function() {
  42            var context;
  43            [1].forEach(function() {context = this;});
  44            expect(context).toBe(function() {return this}.call());
  45        });
  46        it('should iterate all', function() {
  47            testSubject.forEach(function(obj, index) {
  48                actual[index] = obj;
  49            });
  50            expect(actual).toExactlyMatch(expected);
  51        });
  52        it('should iterate all using a context', function() {
  53            var o = { a: actual };
  54    
  55            testSubject.forEach(function(obj, index) {
  56                this.a[index] = obj;
  57            }, o);
  58            expect(actual).toExactlyMatch(expected);
  59        });
  60        
  61        it('should iterate all in an array-like object', function() {
  62            var ts = createArrayLikeFromArray(testSubject);
  63            Array.prototype.forEach.call(ts, function(obj, index) {
  64                actual[index] = obj;
  65            });
  66            expect(actual).toExactlyMatch(expected);
  67        });
  68        it('should iterate all in an array-like object using a context', function() {
  69            var ts = createArrayLikeFromArray(testSubject),
  70                o = { a: actual };
  71            
  72            Array.prototype.forEach.call(ts, function(obj, index) {
  73                this.a[index] = obj;
  74            }, o);
  75            expect(actual).toExactlyMatch(expected);
  76        });
  77
  78        describe('strings', function() {
  79            var str = 'Hello, World!',
  80                toString = Object.prototype.toString;
  81            it('should iterate all in a string', function() {
  82                actual = [];
  83                Array.prototype.forEach.call(str, function(item, index) {
  84                    actual[index] = item;
  85                });
  86                expect(actual).toExactlyMatch(str.split(''));
  87            });
  88            it('should iterate all in a string using a context', function() {
  89                actual = [];
  90                var o = { a: actual };
  91                Array.prototype.forEach.call(str, function(item, index) {
  92                    this.a[index] = item;
  93                }, o);
  94                expect(actual).toExactlyMatch(str.split(''));
  95            });
  96            it('should have String object for third argument of callback', function() {
  97                Array.prototype.forEach.call(str, function(item, index, obj) {
  98                    actual = obj;
  99                });
 100                expect(typeof actual).toBe("object");
 101                expect(toString.call(actual)).toBe("[object String]");
 102            });
 103        });
 104    });
 105    describe('some', function() {
 106        var actual, expected, numberOfRuns;
 107        
 108        beforeEach(function() {
 109            expected = {0:2, 2: undefined, 3:true };
 110            actual = {};
 111            numberOfRuns = 0;
 112        });
 113        
 114        it('should pass the correct values along to the callback', function() {
 115            var callback = jasmine.createSpy('callback');
 116            var array = ['1'];
 117            array.some(callback);
 118            expect(callback).toHaveBeenCalledWith('1', 0, array);
 119        });
 120        it('should not affect elements added to the array after it has begun', function() {
 121            var arr = [1,2,3],
 122                i = 0;
 123            arr.some(function(a) {
 124                i++;
 125                arr.push(a+3);
 126                return i > 3;
 127            });
 128            expect(arr).toEqual([1,2,3,4,5,6]);
 129            expect(i).toBe(3);
 130        });
 131        it('should set the right context when given none', function() {
 132            var context;
 133            [1].some(function() {context = this;});
 134            expect(context).toBe(function() {return this}.call());
 135        });
 136        
 137        it('should return false if it runs to the end', function() {
 138            actual = testSubject.some(function() {});
 139            expect(actual).toBeFalsy();
 140        });
 141        it('should return true if it is stopped somewhere', function() {
 142            actual = testSubject.some(function() { return true; });
 143            expect(actual).toBeTruthy();
 144        });
 145        it('should return false if there are no elements', function() {
 146            actual = [].some(function() { return true; });
 147            expect(actual).toBeFalsy();
 148        });
 149        
 150        it('should stop after 3 elements', function() {
 151            testSubject.some(function(obj, index) {
 152                actual[index] = obj;
 153                numberOfRuns += 1;
 154                if(numberOfRuns == 3) {
 155                    return true;
 156                }
 157                return false;
 158            });
 159            expect(actual).toExactlyMatch(expected);
 160        });
 161        it('should stop after 3 elements using a context', function() {
 162            var o = { a: actual };
 163            testSubject.some(function(obj, index) {
 164                this.a[index] = obj;
 165                numberOfRuns += 1;
 166                if(numberOfRuns == 3) {
 167                    return true;
 168                }
 169                return false;
 170            }, o);
 171            expect(actual).toExactlyMatch(expected);
 172        });
 173    
 174        it('should stop after 3 elements in an array-like object', function() {
 175            var ts = createArrayLikeFromArray(testSubject);
 176            Array.prototype.some.call(ts, function(obj, index) {
 177                actual[index] = obj;
 178                numberOfRuns += 1;
 179                if(numberOfRuns == 3) {
 180                    return true;
 181                }
 182                return false;
 183            });
 184            expect(actual).toExactlyMatch(expected);
 185        });
 186        it('should stop after 3 elements in an array-like object using a context', function() {
 187            var ts = createArrayLikeFromArray(testSubject);
 188            var o = { a: actual };
 189            Array.prototype.some.call(ts, function(obj, index) {
 190                this.a[index] = obj;
 191                numberOfRuns += 1;
 192                if(numberOfRuns == 3) {
 193                    return true;
 194                }
 195                return false;
 196            }, o);
 197            expect(actual).toExactlyMatch(expected);
 198        });
 199    });
 200    describe('every', function() {
 201        var actual, expected, numberOfRuns;
 202        
 203        beforeEach(function() {
 204            expected = {0:2, 2: undefined, 3:true };
 205            actual = {};
 206            numberOfRuns = 0;
 207        });
 208        
 209        it('should pass the correct values along to the callback', function() {
 210            var callback = jasmine.createSpy('callback');
 211            var array = ['1'];
 212            array.every(callback);
 213            expect(callback).toHaveBeenCalledWith('1', 0, array);
 214        });
 215        it('should not affect elements added to the array after it has begun', function() {
 216            var arr = [1,2,3],
 217                i = 0;
 218            arr.every(function(a) {
 219                i++;
 220                arr.push(a+3);
 221                return i <= 3;
 222            });
 223            expect(arr).toEqual([1,2,3,4,5,6]);
 224            expect(i).toBe(3);
 225        });
 226        it('should set the right context when given none', function() {
 227            var context;
 228            [1].every(function() {context = this;});
 229            expect(context).toBe(function() {return this}.call());
 230        });
 231        
 232        it('should return true if the array is empty', function() {
 233            actual = [].every(function() { return true; });
 234            expect(actual).toBeTruthy();
 235            
 236            actual = [].every(function() { return false; });
 237            expect(actual).toBeTruthy();
 238        });
 239        it('should return true if it runs to the end', function() {
 240            actual = [1,2,3].every(function() { return true; });
 241            expect(actual).toBeTruthy();
 242        });
 243        it('should return false if it is stopped before the end', function() {
 244            actual = [1,2,3].every(function() { return false; });
 245            expect(actual).toBeFalsy();
 246        });
 247        
 248        it('should return after 3 elements', function() {
 249            testSubject.every(function(obj, index) {
 250                actual[index] = obj;
 251                numberOfRuns += 1;
 252                if(numberOfRuns == 3) {
 253                    return false;
 254                }
 255                return true;
 256            });
 257            expect(actual).toExactlyMatch(expected);
 258        });
 259        it('should stop after 3 elements using a context', function() {
 260            var o = { a: actual };
 261            testSubject.every(function(obj, index) {
 262                this.a[index] = obj;
 263                numberOfRuns += 1;
 264                if(numberOfRuns == 3) {
 265                    return false;
 266                }
 267                return true;
 268            }, o);
 269            expect(actual).toExactlyMatch(expected);
 270        });
 271    
 272        it('should stop after 3 elements in an array-like object', function() {
 273            var ts = createArrayLikeFromArray(testSubject);
 274            Array.prototype.every.call(ts, function(obj, index) {
 275                actual[index] = obj;
 276                numberOfRuns += 1;
 277                if(numberOfRuns == 3) {
 278                    return false;
 279                }
 280                return true;
 281            });
 282            expect(actual).toExactlyMatch(expected);
 283        });
 284        it('should stop after 3 elements in an array-like object using a context', function() {
 285            var ts = createArrayLikeFromArray(testSubject);
 286            var o = { a: actual };
 287            Array.prototype.every.call(ts, function(obj, index) {
 288                this.a[index] = obj;
 289                numberOfRuns += 1;
 290                if(numberOfRuns == 3) {
 291                    return false;
 292                }
 293                return true;
 294            }, o);
 295            expect(actual).toExactlyMatch(expected);
 296        });
 297    });
 298    
 299    describe('indexOf', function() {
 300        "use strict";
 301        var actual, expected, testSubject;
 302        
 303        beforeEach(function() {
 304            testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
 305            delete testSubject[1];
 306    
 307        });
 308    
 309        it('should find the element', function() {
 310            expected = 4;
 311            actual = testSubject.indexOf('hej');
 312            expect(actual).toEqual(expected);
 313        });
 314        it('should not find the element', function() {
 315            expected = -1;
 316            actual = testSubject.indexOf('mus');
 317            expect(actual).toEqual(expected);
 318        });
 319        it('should find undefined as well', function() {
 320            expected = -1;
 321            actual = testSubject.indexOf(undefined);
 322            expect(actual).not.toEqual(expected);
 323        });
 324        it('should skip unset indexes', function() {
 325            expected = 2;
 326            actual = testSubject.indexOf(undefined);
 327            expect(actual).toEqual(expected);
 328        });
 329        it('should use a strict test', function() {
 330            actual = testSubject.indexOf(null);
 331            expect(actual).toEqual(5);
 332            
 333            actual = testSubject.indexOf('2');
 334            expect(actual).toEqual(-1);
 335        });
 336        it('should skip the first if fromIndex is set', function() {
 337            expect(testSubject.indexOf(2, 2)).toEqual(6);
 338            expect(testSubject.indexOf(2, 0)).toEqual(0);
 339            expect(testSubject.indexOf(2, 6)).toEqual(6);
 340        });
 341        it('should work with negative fromIndex', function() {
 342            expect(testSubject.indexOf(2, -3)).toEqual(6);
 343            expect(testSubject.indexOf(2, -9)).toEqual(0);
 344        });
 345        it('should work with fromIndex being greater than the length', function() {
 346            expect(testSubject.indexOf(0, 20)).toEqual(-1);
 347        });
 348        it('should work with fromIndex being negative and greater than the length', function() {
 349            expect(testSubject.indexOf('hej', -20)).toEqual(4);
 350        });
 351        
 352        describe('Array-like', function ArrayLike() {
 353            var indexOf = Array.prototype.indexOf,
 354                testAL;
 355            beforeEach(function beforeEach() {
 356                testAL = {};
 357                testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
 358                testSubject.forEach(function (o,i) {
 359                    testAL[i] = o;
 360                });
 361                testAL.length = testSubject.length;
 362            });
 363            it('should find the element (array-like)', function() {
 364                expected = 4;
 365                actual = indexOf.call(testAL, 'hej');
 366                expect(actual).toEqual(expected);
 367            });
 368            it('should not find the element (array-like)', function() {
 369                expected = -1;
 370                actual = indexOf.call(testAL, 'mus');
 371                expect(actual).toEqual(expected);
 372            });
 373            it('should find undefined as well (array-like)', function() {
 374                expected = -1;
 375                actual = indexOf.call(testAL, undefined);
 376                expect(actual).not.toEqual(expected);
 377            });
 378            it('should skip unset indexes (array-like)', function() {
 379                expected = 2;
 380                actual = indexOf.call(testAL, undefined);
 381                expect(actual).toEqual(expected);
 382            });
 383            it('should use a strict test (array-like)', function() {
 384                actual = Array.prototype.indexOf.call(testAL, null);
 385                expect(actual).toEqual(5);
 386                
 387                actual = Array.prototype.indexOf.call(testAL, '2');
 388                expect(actual).toEqual(-1);
 389            });
 390            it('should skip the first if fromIndex is set (array-like)', function() {
 391                expect(indexOf.call(testAL, 2, 2)).toEqual(6);
 392                expect(indexOf.call(testAL, 2, 0)).toEqual(0);
 393                expect(indexOf.call(testAL, 2, 6)).toEqual(6);
 394            });
 395            it('should work with negative fromIndex (array-like)', function() {
 396                expect(indexOf.call(testAL, 2, -3)).toEqual(6);
 397                expect(indexOf.call(testAL, 2, -9)).toEqual(0);
 398            });
 399            it('should work with fromIndex being greater than the length (array-like)', function() {
 400                expect(indexOf.call(testAL, 0, 20)).toEqual(-1);
 401            });
 402            it('should work with fromIndex being negative and greater than the length (array-like)', function() {
 403                expect(indexOf.call(testAL, 'hej', -20)).toEqual(4);
 404            });
 405        });
 406    });
 407    describe('lastIndexOf', function() {
 408        "use strict";
 409        var actual, expected, testSubject, testAL;
 410        
 411        beforeEach(function() {
 412            testSubject = [2, 3, undefined, true, 'hej', null, 2, 3, false, 0];
 413            delete testSubject[1];
 414            delete testSubject[7];
 415        });
 416        describe('Array', function() {
 417            it('should find the element', function() {
 418                expected = 4;
 419                actual = testSubject.lastIndexOf('hej');
 420                expect(actual).toEqual(expected);
 421            });
 422            it('should not find the element', function() {
 423                expected = -1;
 424                actual = testSubject.lastIndexOf('mus');
 425                expect(actual).toEqual(expected);
 426            });
 427            it('should find undefined as well', function() {
 428                expected = -1;
 429                actual = testSubject.lastIndexOf(undefined);
 430                expect(actual).not.toEqual(expected);
 431            });
 432            it('should skip unset indexes', function() {
 433                expected = 2;
 434                actual = testSubject.lastIndexOf(undefined);
 435                expect(actual).toEqual(expected);
 436            });
 437            it('should use a strict test', function() {
 438                actual = testSubject.lastIndexOf(null);
 439                expect(actual).toEqual(5);
 440                
 441                actual = testSubject.lastIndexOf('2');
 442                expect(actual).toEqual(-1);
 443            });
 444            it('should skip the first if fromIndex is set', function() {
 445                expect(testSubject.lastIndexOf(2, 2)).toEqual(0);
 446                expect(testSubject.lastIndexOf(2, 0)).toEqual(0);
 447                expect(testSubject.lastIndexOf(2, 6)).toEqual(6);
 448            });
 449            it('should work with negative fromIndex', function() {
 450                expect(testSubject.lastIndexOf(2, -3)).toEqual(6);
 451                expect(testSubject.lastIndexOf(2, -9)).toEqual(0);
 452            });
 453            it('should work with fromIndex being greater than the length', function() {
 454                expect(testSubject.lastIndexOf(2, 20)).toEqual(6);
 455            });
 456            it('should work with fromIndex being negative and greater than the length', function() {
 457                expect(testSubject.lastIndexOf(2, -20)).toEqual(-1);
 458            });
 459        });
 460    
 461        describe('Array like', function() {
 462            var lastIndexOf = Array.prototype.lastIndexOf,
 463                testAL;
 464            beforeEach(function() {
 465                testAL = {};
 466                testSubject.forEach(function (o,i) {
 467                    testAL[i] = o;
 468                });
 469                testAL.length = testSubject.length;
 470            });
 471            it('should find the element (array-like)', function() {
 472                expected = 4;
 473                actual = lastIndexOf.call(testAL, 'hej');
 474                expect(actual).toEqual(expected);
 475            });
 476            it('should not find the element (array-like)', function() {
 477                expected = -1;
 478                actual = lastIndexOf.call(testAL, 'mus');
 479                expect(actual).toEqual(expected);
 480            });
 481            it('should find undefined as well (array-like)', function() {
 482                expected = -1;
 483                actual = lastIndexOf.call(testAL, undefined);
 484                expect(actual).not.toEqual(expected);
 485            });
 486            it('should skip unset indexes (array-like)', function() {
 487                expected = 2;
 488                actual = lastIndexOf.call(testAL, undefined);
 489                expect(actual).toEqual(expected);
 490            });
 491            it('should use a strict test (array-like)', function() {
 492                actual = lastIndexOf.call(testAL, null);
 493                expect(actual).toEqual(5);
 494                
 495                actual = lastIndexOf.call(testAL, '2');
 496                expect(actual).toEqual(-1);
 497            });
 498            it('should skip the first if fromIndex is set', function() {
 499                expect(lastIndexOf.call(testAL, 2, 2)).toEqual(0);
 500                expect(lastIndexOf.call(testAL, 2, 0)).toEqual(0);
 501                expect(lastIndexOf.call(testAL, 2, 6)).toEqual(6);
 502            });
 503            it('should work with negative fromIndex', function() {
 504                expect(lastIndexOf.call(testAL, 2, -3)).toEqual(6);
 505                expect(lastIndexOf.call(testAL, 2, -9)).toEqual(0);
 506            });
 507            it('should work with fromIndex being greater than the length', function() {
 508                expect(lastIndexOf.call(testAL, 2, 20)).toEqual(6);
 509            });
 510            it('should work with fromIndex being negative and greater than the length', function() {
 511                expect(lastIndexOf.call(testAL, 2, -20)).toEqual(-1);
 512            });
 513        });
 514    });
 515    
 516    describe('filter', function() {
 517        var filteredArray,
 518            callback = function callback(o, i, arr) {
 519                return (
 520                    i != 3 && i != 5
 521                );
 522            };
 523        
 524        beforeEach(function() {
 525            testSubject = [2, 3, undefined, true, 'hej', 3, null, false, 0];
 526            delete testSubject[1];
 527            filteredArray = [2, undefined, 'hej', null, false, 0];
 528        });
 529        describe('Array object', function() {
 530
 531            it('should call the callback with the proper arguments', function() {
 532                var callback = jasmine.createSpy('callback'),
 533                    arr = ['1'];
 534                arr.filter(callback);
 535                expect(callback).toHaveBeenCalledWith('1', 0, arr);
 536            });
 537            it('should not affect elements added to the array after it has begun', function() {
 538                var arr = [1,2,3],
 539                    i = 0;
 540                arr.filter(function(a) {
 541                    i++;
 542                    if(i <= 4) {
 543                        arr.push(a+3);
 544                    }
 545                    return true;
 546                });
 547                expect(arr).toEqual([1,2,3,4,5,6]);
 548                expect(i).toBe(3);
 549            });
 550            it('should skip non-set values', function() {
 551                var passedValues = {};
 552                testSubject = [1,2,3,4];
 553                delete testSubject[1];
 554                testSubject.filter(function(o, i) {
 555                    passedValues[i] = o;
 556                    return true;
 557                });
 558                expect(passedValues).toExactlyMatch(testSubject);
 559            });
 560            it('should pass the right context to the filter', function() {
 561                var passedValues = {};
 562                testSubject = [1,2,3,4];
 563                delete testSubject[1];
 564                testSubject.filter(function(o, i) {
 565                    this[i] = o;
 566                    return true;
 567                }, passedValues);
 568                expect(passedValues).toExactlyMatch(testSubject);
 569            });
 570            it('should set the right context when given none', function() {
 571                var context;
 572                [1].filter(function() {context = this;});
 573                expect(context).toBe(function() {return this}.call());
 574            });
 575            it('should remove only the values for which the callback returns false', function() {
 576                var result = testSubject.filter(callback);
 577                expect(result).toExactlyMatch(filteredArray);
 578            });
 579            it('should leave the original array untouched', function() {
 580                var copy = testSubject.slice();
 581                testSubject.filter(callback);
 582                expect(testSubject).toExactlyMatch(copy);
 583            });
 584            it('should not be affected by same-index mutation', function () {
 585                var results = [1, 2, 3]
 586                .filter(function (value, index, array) {
 587                    array[index] = 'a';
 588                    return true;
 589                });
 590                expect(results).toEqual([1, 2, 3]);
 591            });
 592        });
 593        describe('Array like', function() {
 594            beforeEach(function() {
 595                testSubject = createArrayLikeFromArray(testSubject);
 596            });
 597            it('should call the callback with the proper arguments', function() {
 598                var callback = jasmine.createSpy('callback'),
 599                    arr = createArrayLikeFromArray(['1']);
 600                Array.prototype.filter.call(arr, callback);
 601                expect(callback).toHaveBeenCalledWith('1', 0, arr);
 602            });
 603            it('should not affect elements added to the array after it has begun', function() {
 604                var arr = createArrayLikeFromArray([1,2,3]),
 605                    i = 0;
 606                Array.prototype.filter.call(arr, function(a) {
 607                    i++;
 608                    if(i <= 4) {
 609                        arr[i+2] = a+3;
 610                    }
 611                    return true;
 612                });
 613                delete arr.length;
 614                expect(arr).toExactlyMatch([1,2,3,4,5,6]);
 615                expect(i).toBe(3);
 616            });
 617            it('should skip non-set values', function() {
 618                var passedValues = {};
 619                testSubject = createArrayLikeFromArray([1,2,3,4]);
 620                delete testSubject[1];
 621                Array.prototype.filter.call(testSubject, function(o, i) {
 622                    passedValues[i] = o;
 623                    return true;
 624                });
 625                delete testSubject.length;
 626                expect(passedValues).toExactlyMatch(testSubject);
 627            });
 628            it('should set the right context when given none', function() {
 629                var context;
 630                Array.prototype.filter.call(createArrayLikeFromArray([1]), function() {context = this;}, undefined);
 631                expect(context).toBe(function() {return this}.call());
 632            });
 633            it('should pass the right context to the filter', function() {
 634                var passedValues = {};
 635                testSubject = createArrayLikeFromArray([1,2,3,4]);
 636                delete testSubject[1];
 637                Array.prototype.filter.call(testSubject, function(o, i) {
 638                    this[i] = o;
 639                    return true;
 640                }, passedValues);
 641                delete testSubject.length;
 642                expect(passedValues).toExactlyMatch(testSubject);
 643            });
 644            it('should remove only the values for which the callback returns false', function() {
 645                var result = Array.prototype.filter.call(testSubject, callback);
 646                expect(result).toExactlyMatch(filteredArray);
 647            });
 648            it('should leave the original array untouched', function() {
 649                var copy = createArrayLikeFromArray(testSubject);
 650                Array.prototype.filter.call(testSubject, callback);
 651                expect(testSubject).toExactlyMatch(copy);
 652            });
 653        });
 654    });
 655    describe('map', function() {
 656        var callback;
 657        beforeEach(function() {
 658            var i = 0;
 659            callback = function() {
 660                return i++;
 661            };
 662        });
 663        describe('Array object', function() {
 664            it('should call callback with the right parameters', function() {
 665                var callback = jasmine.createSpy('callback'),
 666                    array = [1];
 667                array.map(callback);
 668                expect(callback).toHaveBeenCalledWith(1, 0, array);
 669            });
 670            it('should set the context correctly', function() {
 671                var context = {};
 672                testSubject.map(function(o,i) {
 673                    this[i] = o;
 674                }, context);
 675                expect(context).toExactlyMatch(testSubject);
 676            });
 677            it('should set the right context when given none', function() {
 678                var context;
 679                [1].map(function() {context = this;});
 680                expect(context).toBe(function() {return this}.call());
 681            });
 682            it('should not change the array it is called on', function() {
 683                var copy = testSubject.slice();
 684                testSubject.map(callback);
 685                expect(testSubject).toExactlyMatch(copy);
 686            });
 687            it('should only run for the number of objects in the array when it started', function() {
 688                var arr = [1,2,3],
 689                    i = 0;
 690                arr.map(function(o) {
 691                    arr.push(o+3);
 692                    i++;
 693                    return o;
 694                });
 695                expect(arr).toExactlyMatch([1,2,3,4,5,6]);
 696                expect(i).toBe(3);
 697            });
 698            it('should properly translate the values as according to the callback', function() {
 699                var result = testSubject.map(callback),
 700                    expected = [0,0,1,2,3,4,5,6];
 701                delete expected[1];
 702                expect(result).toExactlyMatch(expected);
 703            });
 704            it('should skip non-existing values', function() {
 705                var array = [1,2,3,4], 
 706                    i = 0;
 707                delete array[2];
 708                array.map(function() {
 709                    i++;
 710                });
 711                expect(i).toBe(3);
 712            });
 713        });
 714        describe('Array-like', function() {
 715            beforeEach(function() {
 716                testSubject = createArrayLikeFromArray(testSubject);
 717            });
 718            it('should call callback with the right parameters', function() {
 719                var callback = jasmine.createSpy('callback'),
 720                    array = createArrayLikeFromArray([1]);
 721                Array.prototype.map.call(array, callback);
 722                expect(callback).toHaveBeenCalledWith(1, 0, array);
 723            });
 724            it('should set the context correctly', function() {
 725                var context = {};
 726                Array.prototype.map.call(testSubject, function(o,i) {
 727                    this[i] = o;
 728                }, context);
 729                delete testSubject.length;
 730                expect(context).toExactlyMatch(testSubject);
 731            });
 732            it('should set the right context when given none', function() {
 733                var context;
 734                Array.prototype.map.call(createArrayLikeFromArray([1]), function() {context = this;});
 735                expect(context).toBe(function() {return this}.call());
 736            });
 737            it('should not change the array it is called on', function() {
 738                var copy = createArrayLikeFromArray(testSubject);
 739                Array.prototype.map.call(testSubject, callback);
 740                expect(testSubject).toExactlyMatch(copy);
 741            });
 742            it('should only run for the number of objects in the array when it started', function() {
 743                var arr = createArrayLikeFromArray([1,2,3]),
 744                    i = 0;
 745                Array.prototype.map.call(arr, function(o) {
 746                    Array.prototype.push.call(arr, o+3);
 747                    i++;
 748                    return o;
 749                });
 750                delete arr.length;
 751                expect(arr).toExactlyMatch([1,2,3,4,5,6]);
 752                expect(i).toBe(3);
 753            });
 754            it('should properly translate the values as according to the callback', function() {
 755                var result = Array.prototype.map.call(testSubject, callback),
 756                    expected = [0,0,1,2,3,4,5,6];
 757                delete expected[1];
 758                expect(result).toExactlyMatch(expected);
 759            });
 760            it('should skip non-existing values', function() {
 761                var array = createArrayLikeFromArray([1,2,3,4]), 
 762                    i = 0;
 763                delete array[2];
 764                Array.prototype.map.call(array, function() {
 765                    i++;
 766                });
 767                expect(i).toBe(3);
 768            });
 769        });
 770    });
 771    
 772    describe('reduce', function() {
 773        beforeEach(function() {
 774            testSubject = [1,2,3];
 775        });
 776        
 777        describe('Array', function() {
 778            it('should pass the correct arguments to the callback', function() {
 779                var spy = jasmine.createSpy().andReturn(0);
 780                testSubject.reduce(spy);
 781                expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);
 782            });
 783            it('should start with the right initialValue', function() {
 784                var spy = jasmine.createSpy().andReturn(0);
 785                testSubject.reduce(spy, 0);
 786                expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);
 787            });
 788            it('should not affect elements added to the array after it has begun', function() {
 789                var arr = [1,2,3],
 790                    i = 0;
 791                arr.reduce(function(a, b) {
 792                    i++;
 793                    if(i <= 4) {
 794                        arr.push(a+3);
 795                    };
 796                    return b;
 797                });
 798                expect(arr).toEqual([1,2,3,4,5]);
 799                expect(i).toBe(2);
 800            });
 801            it('should work as expected for empty arrays', function() {
 802                var spy = jasmine.createSpy();
 803                expect(function() {
 804                    [].reduce(spy);
 805                }).toThrow();
 806                expect(spy).not.toHaveBeenCalled();
 807            });
 808            it('should throw correctly if no callback is given', function() {
 809                expect(function() {
 810                    testSubject.reduce();
 811                }).toThrow();
 812            });
 813            it('should return the expected result', function() {
 814                expect(testSubject.reduce(function(a,b) {
 815                    return (a||'').toString()+(b||'').toString();
 816                })).toEqual(testSubject.join(''));
 817            });
 818            it('should not directly affect the passed array', function() {
 819                var copy = testSubject.slice();
 820                testSubject.reduce(function(a,b) {
 821                    return a+b;
 822                });
 823                expect(testSubject).toEqual(copy);
 824            });
 825            it('should skip non-set values', function() {
 826                delete testSubject[1];
 827                var visited = {};
 828                testSubject.reduce(function(a,b) {
 829                    if(a)
 830                        visited[a] = true;
 831                    if(b)
 832                        visited[b] = true;
 833                    return 0;
 834                });
 835                
 836                expect(visited).toEqual({ '1': true, '3': true });
 837            });
 838            it('should have the right length', function() {
 839                expect(testSubject.reduce.length).toBe(1);
 840            });
 841        });
 842        describe('Array-like objects', function() {
 843            beforeEach(function() {
 844                testSubject = createArrayLikeFromArray(testSubject);
 845                testSubject.reduce = Array.prototype.reduce;
 846            });
 847            it('should pass the correct arguments to the callback', function() {
 848                var spy = jasmine.createSpy().andReturn(0);
 849                testSubject.reduce(spy);
 850                expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);
 851            });
 852            it('should start with the right initialValue', function() {
 853                var spy = jasmine.createSpy().andReturn(0);
 854                testSubject.reduce(spy, 0);
 855                expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);
 856            });
 857            it('should not affect elements added to the array after it has begun', function() {
 858                var arr = createArrayLikeFromArray([1,2,3]),
 859                    i = 0;
 860                Array.prototype.reduce.call(arr, function(a, b) {
 861                    i++;
 862                    if(i <= 4) {
 863                        arr[i+2] = a+3;
 864                    };
 865                    return b;
 866                });
 867                expect(arr).toEqual({
 868                    0: 1,
 869                    1: 2,
 870                    2: 3,
 871                    3: 4,
 872                    4: 5,
 873                    length: 3
 874                });
 875                expect(i).toBe(2);
 876            });
 877            it('should work as expected for empty arrays', function() {
 878                var spy = jasmine.createSpy();
 879                expect(function() {
 880                    Array.prototype.reduce.call({length: 0}, spy);
 881                }).toThrow();
 882                expect(spy).not.toHaveBeenCalled();
 883            });
 884            it('should throw correctly if no callback is given', function() {
 885                expect(function() {
 886                    testSubject.reduce();
 887                }).toThrow();
 888            });
 889            it('should return the expected result', function() {
 890                expect(testSubject.reduce(function(a,b) {
 891                    return (a||'').toString()+(b||'').toString();
 892                })).toEqual('123');
 893            });
 894            it('should not directly affect the passed array', function() {
 895                var copy = createArrayLikeFromArray(testSubject);
 896                testSubject.reduce(function(a,b) {
 897                    return a+b;
 898                });
 899                delete(testSubject.reduce);
 900                expect(testSubject).toEqual(copy);
 901            });
 902            it('should skip non-set values', function() {
 903                delete testSubject[1];
 904                var visited = {};
 905                testSubject.reduce(function(a,b) {
 906                    if(a)
 907                        visited[a] = true;
 908                    if(b)
 909                        visited[b] = true;
 910                    return 0;
 911                });
 912                
 913                expect(visited).toEqual({ '1': true, '3': true });
 914            });
 915            it('should have the right length', function() {
 916                expect(testSubject.reduce.length).toBe(1);
 917            });
 918        });
 919    });
 920    describe('reduceRight', function() {
 921        beforeEach(function() {
 922            testSubject = [1,2,3];
 923        });
 924        
 925        describe('Array', function() {
 926            it('should pass the correct arguments to the callback', function() {
 927                var spy = jasmine.createSpy().andReturn(0);
 928                testSubject.reduceRight(spy);
 929                expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);
 930            });
 931            it('should start with the right initialValue', function() {
 932                var spy = jasmine.createSpy().andReturn(0);
 933                testSubject.reduceRight(spy, 0);
 934                expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);
 935            });
 936            it('should not affect elements added to the array after it has begun', function() {
 937                var arr = [1,2,3],
 938                    i = 0;
 939                arr.reduceRight(function(a, b) {
 940                    i++;
 941                    if(i <= 4) {
 942                        arr.push(a+3);
 943                    };
 944                    return b;
 945                });
 946                expect(arr).toEqual([1,2,3,6,5]);
 947                expect(i).toBe(2);
 948            });
 949            it('should work as expected for empty arrays', function() {
 950                var spy = jasmine.createSpy();
 951                expect(function() {
 952                    [].reduceRight(spy);
 953                }).toThrow();
 954                expect(spy).not.toHaveBeenCalled();
 955            });
 956            it('should throw correctly if no callback is given', function() {
 957                expect(function() {
 958                    testSubject.reduceRight();
 959                }).toThrow();
 960            });
 961            it('should return the expected result', function() {
 962                expect(testSubject.reduceRight(function(a,b) {
 963                    return (a||'').toString()+(b||'').toString();
 964                })).toEqual('321');
 965            });
 966            it('should not directly affect the passed array', function() {
 967                var copy = testSubject.slice();
 968                testSubject.reduceRight(function(a,b) {
 969                    return a+b;
 970                });
 971                expect(testSubject).toEqual(copy);
 972            });
 973            it('should skip non-set values', function() {
 974                delete testSubject[1];
 975                var visited = {};
 976                testSubject.reduceRight(function(a,b) {
 977                    if(a)
 978                        visited[a] = true;
 979                    if(b)
 980                        visited[b] = true;
 981                    return 0;
 982                });
 983                
 984                expect(visited).toEqual({ '1': true, '3': true });
 985            });
 986            it('should have the right length', function() {
 987                expect(testSubject.reduceRight.length).toBe(1);
 988            });
 989        });
 990        describe('Array-like objects', function() {
 991            beforeEach(function() {
 992                testSubject = createArrayLikeFromArray(testSubject);
 993                testSubject.reduceRight = Array.prototype.reduceRight;
 994            });
 995            it('should pass the correct arguments to the callback', function() {
 996                var spy = jasmine.createSpy().andReturn(0);
 997                testSubject.reduceRight(spy);
 998                expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);
 999            });
1000            it('should start with the right initialValue', function() {
1001                var spy = jasmine.createSpy().andReturn(0);
1002                testSubject.reduceRight(spy, 0);
1003                expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);
1004            });
1005            it('should not affect elements added to the array after it has begun', function() {
1006                var arr = createArrayLikeFromArray([1,2,3]),
1007                    i = 0;
1008                Array.prototype.reduceRight.call(arr, function(a, b) {
1009                    i++;
1010                    if(i <= 4) {
1011                        arr[i+2] = a+3;
1012                    };
1013                    return b;
1014                });
1015                expect(arr).toEqual({
1016                    0: 1,
1017                    1: 2,
1018                    2: 3,
1019                    3: 6,
1020                    4: 5,
1021                    length: 3 // does not get updated on property assignment
1022                });
1023                expect(i).toBe(2);
1024            });
1025            it('should work as expected for empty arrays', function() {
1026                var spy = jasmine.createSpy();
1027                expect(function() {
1028                    Array.prototype.reduceRight.call({length:0}, spy);
1029                }).toThrow();
1030                expect(spy).not.toHaveBeenCalled();
1031            });
1032            it('should throw correctly if no callback is given', function() {
1033                expect(function() {
1034                    testSubject.reduceRight();
1035                }).toThrow();
1036            });
1037            it('should return the expected result', function() {
1038                expect(testSubject.reduceRight(function(a,b) {
1039                    return (a||'').toString()+(b||'').toString();
1040                })).toEqual('321');
1041            });
1042            it('should not directly affect the passed array', function() {
1043                var copy = createArrayLikeFromArray(testSubject);
1044                testSubject.reduceRight(function(a,b) {
1045                    return a+b;
1046                });
1047                delete(testSubject.reduceRight);
1048                expect(testSubject).toEqual(copy);
1049            });
1050            it('should skip non-set values', function() {
1051                delete testSubject[1];
1052                var visited = {};
1053                testSubject.reduceRight(function(a,b) {
1054                    if(a)
1055                        visited[a] = true;
1056                    if(b)
1057                        visited[b] = true;
1058                    return 0;
1059                });
1060                
1061                expect(visited).toEqual({ '1': true, '3': true });
1062            });
1063            it('should have the right length', function() {
1064                expect(testSubject.reduceRight.length).toBe(1);
1065            });
1066        });
1067    });
1068
1069    describe('isArray', function () {
1070        it('should work for Array', function () {
1071            var ret = Array.isArray([]);
1072
1073            expect(ret).toBe(true);
1074        });
1075
1076        it('should fail for other objects', function () {
1077            var objects = [
1078                "someString",
1079                true,
1080                false,
1081                42,
1082                0,
1083                {},
1084                Object.create(null),
1085                /foo/,
1086                arguments,
1087                document.getElementsByTagName("div")
1088            ];
1089
1090            objects.forEach(function (v) {
1091                expect(Array.isArray(v)).toBe(false);
1092            });
1093        });
1094    });
1095
1096    describe('unshift', function () {
1097        it('should return length', function () {
1098            expect([].unshift(0)).toEqual(1);
1099        });
1100    });
1101
1102    describe('splice', function () {
1103        var b = ["b"],
1104            a = [1, "a", b],
1105            test;
1106        beforeEach(function() {
1107            test = a.slice(0);
1108        });
1109        
1110        it('basic implementation test 1', function () {
1111            expect(test.splice(0)).toEqual(a);
1112        });
1113        it('basic implementation test 2', function () {
1114            test.splice(0, 2);
1115            expect(test).toEqual([b]);
1116        });            
1117                 
1118        
1119        it('should do nothing if method called with no arguments', function () {
1120            expect(test.splice()).toEqual([]);
1121            expect(test).toEqual(a);
1122        });
1123        //TODO:: Is this realy TRUE behavior?
1124        it('should set first argument to 0 if first argument is set but undefined', function () {
1125            var test2 = test.slice(0);
1126            expect(test.splice(void 0, 2)).toEqual(test2.splice(0, 2));
1127            expect(test).toEqual(test2);
1128        });
1129
1130        it('should deleted and return all items after "start" when second argument is undefined', function () {
1131            expect(test.splice(0)).toEqual(a);
1132            expect(test).toEqual([]);
1133        });
1134        it('should deleted and return all items after "start" when second argument is undefined', function () {
1135            expect(test.splice(2)).toEqual([b]);
1136            expect(test).toEqual([1, "a"]);
1137        });
1138        it('runshould have the right length', function () {
1139            expect(test.splice.length).toBe(2);
1140        }); 
1141    });
1142
1143    
1144});