it('should treat null as an empty list', () => {
   differ.diff(['a', 'b']);
   expect(iterableDifferToString(differ.diff(null !) !)).toEqual(iterableChangesAsString({
     previous: ['a[0->null]', 'b[1->null]'],
     removals: ['a[0->null]', 'b[1->null]']
   }));
 });
 it('should ignore [NaN] != [NaN]', () => {
   const l = [NaN];
   differ.check(l);
   differ.check(l);
   expect(iterableDifferToString(differ))
       .toEqual(iterableChangesAsString({collection: [NaN], previous: [NaN]}));
 });
      it('should track removals normally', () => {
        differ.check(['a', 'b', 'c', 'd']);
        differ.check(['e', 'f', 'g', 'h']);
        differ.check(['e', 'f', 'h']);

        expect(iterableDifferToString(differ)).toEqual(iterableChangesAsString({
          collection: ['e', 'f', 'h'],
          previous: ['e', 'f', 'h', 'h[3->null]'],
          removals: ['h[3->null]'],
          identityChanges: ['h']
        }));
      });
      it('should support insertions/moves', () => {
        const l = ['a', 'a', 'b', 'b'];
        differ.check(l);

        l.splice(0, 0, 'b');
        differ.check(l);
        expect(iterableDifferToString(differ)).toEqual(iterableChangesAsString({
          collection: ['b[2->0]', 'a[0->1]', 'a[1->2]', 'b', 'b[null->4]'],
          previous: ['a[0->1]', 'a[1->2]', 'b[2->0]', 'b'],
          additions: ['b[null->4]'],
          moves: ['b[2->0]', 'a[0->1]', 'a[1->2]']
        }));
      });
      it('should support duplicates', () => {
        const l = ['a', 'a', 'a', 'b', 'b'];
        differ.check(l);

        l.splice(0, 1);
        differ.check(l);
        expect(iterableDifferToString(differ)).toEqual(iterableChangesAsString({
          collection: ['a', 'a', 'b[3->2]', 'b[4->3]'],
          previous: ['a', 'a', 'a[2->null]', 'b[3->2]', 'b[4->3]'],
          moves: ['b[3->2]', 'b[4->3]'],
          removals: ['a[2->null]']
        }));
      });
      it('should detect [NaN] moves', () => {
        const l: any[] = [NaN, NaN];
        differ.check(l);

        l.unshift('foo');
        differ.check(l);
        expect(iterableDifferToString(differ)).toEqual(iterableChangesAsString({
          collection: ['foo[null->0]', 'NaN[0->1]', 'NaN[1->2]'],
          previous: ['NaN[0->1]', 'NaN[1->2]'],
          additions: ['foo[null->0]'],
          moves: ['NaN[0->1]', 'NaN[1->2]']
        }));
      });
 it('support re-insertion', () => {
   const l = ['a', '*', '*', 'd', '-', '-', '-', 'e'];
   differ.check(l);
   l[1] = 'b';
   l[5] = 'c';
   differ.check(l);
   expect(iterableDifferToString(differ)).toEqual(iterableChangesAsString({
     collection: ['a', 'b[null->1]', '*[1->2]', 'd', '-', 'c[null->5]', '-[5->6]', 'e'],
     previous: ['a', '*[1->2]', '*[2->null]', 'd', '-', '-[5->6]', '-[6->null]', 'e'],
     additions: ['b[null->1]', 'c[null->5]'],
     moves: ['*[1->2]', '-[5->6]'],
     removals: ['*[2->null]', '-[6->null]'],
   }));
 });
      it('should handle swapping element', () => {
        const l = [1, 2];
        differ.check(l);

        l.length = 0;
        l.push(2);
        l.push(1);
        differ.check(l);
        expect(iterableDifferToString(differ)).toEqual(iterableChangesAsString({
          collection: ['2[1->0]', '1[0->1]'],
          previous: ['1[0->1]', '2[1->0]'],
          moves: ['2[1->0]', '1[0->1]']
        }));
      });
      it('should not report unnecessary moves', () => {
        const l = ['a', 'b', 'c'];
        differ.check(l);

        l.length = 0;
        l.push('b');
        l.push('a');
        l.push('c');
        differ.check(l);
        expect(iterableDifferToString(differ)).toEqual(iterableChangesAsString({
          collection: ['b[1->0]', 'a[0->1]', 'c'],
          previous: ['a[0->1]', 'b[1->0]', 'c'],
          moves: ['b[1->0]', 'a[0->1]']
        }));
      });
           () => {
             differ = new DefaultIterableDiffer((index: number) => index);

             const startData = [1, 2, 3, 4];
             const endData = [5, 6, 7, 8];

             differ = differ.diff(startData) !;
             differ = differ.diff(endData) !;

             const operations: string[] = [];
             differ.forEachOperation((item: any, prev: number, next: number) => {
               const value = modifyArrayUsingOperation(startData, endData, prev, next);
               operations.push(stringifyItemChange(item, prev, next, item.previousIndex));
             });

             expect(operations).toEqual([]);
           });