function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

describe('UndoRedo', function () {
  var id = 'testContainer';
  beforeEach(function () {
    this.$container = $("<div id=\"".concat(id, "\"></div>")).appendTo('body');
  });
  afterEach(function () {
    if (this.$container) {
      destroy();
      this.$container.remove();
    }
  });
  describe('core features', function () {
    describe('Array data', function () {
      describe('undo', function () {
        it('should undo single change', function () {
          handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          var HOT = getInstance();
          setDataAtCell(0, 0, 'X1');
          expect(getDataAtCell(0, 0)).toBe('X1');
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('A1');
        });
        it('should undo single change on cell with validator', function (done) {
          handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          var HOT = getInstance();
          setDataAtCell(0, 0, 'X1');
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            HOT.undo();
          }, 200);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('A1');
            done();
          }, 400);
        });
        it('should undo creation of a single row', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row');
          expect(countRows()).toEqual(3);
          HOT.undo();
          expect(countRows()).toEqual(2);
        });
        it('should undo creation of multiple rows', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row', 0, 5);
          expect(countRows()).toEqual(7);
          HOT.undo();
          expect(countRows()).toEqual(2);
        });
        it('should undo creation of multiple rows with minSpareRows', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 1),
            minSpareRows: 2
          });
          expect(getData()).toEqual([['A1'], ['A2'], [null], [null]]);
          setDataAtCell(2, 0, 'A3');
          setDataAtCell(4, 0, 'A4');
          expect(getData()).toEqual([['A1'], ['A2'], ['A3'], [null], ['A4'], [null], [null]]);
          HOT.undo();
          HOT.undo();
          expect(getData()).toEqual([['A1'], ['A2'], [null], [null]]);
        });
        it('should undo removal of single row', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(3, 2)
          });
          expect(countRows()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          alter('remove_row', 1);
          expect(countRows()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A3');
          expect(getDataAtCell(1, 1)).toEqual('B3');
          HOT.undo();
          expect(countRows()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
        });
        it('should undo removal of multiple rows', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(4, 2)
          });
          expect(countRows()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          expect(getDataAtCell(3, 0)).toEqual('A4');
          expect(getDataAtCell(3, 1)).toEqual('B4');
          alter('remove_row', 1, 2);
          expect(countRows()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A4');
          expect(getDataAtCell(1, 1)).toEqual('B4');
          HOT.undo();
          expect(countRows()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          expect(getDataAtCell(3, 0)).toEqual('A4');
          expect(getDataAtCell(3, 1)).toEqual('B4');
        });
        it('should undo removal of single row after column sorting', function () {
          handsontable({
            data: Handsontable.helper.createSpreadsheetData(3, 2),
            colHeaders: true,
            columnSorting: true
          });
          expect(countRows()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          getPlugin('ColumnSorting').sort({
            column: 0,
            sortOrder: 'desc'
          });
          expect(countRows()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A3');
          expect(getDataAtCell(0, 1)).toEqual('B3');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A1');
          expect(getDataAtCell(2, 1)).toEqual('B1');
          alter('remove_row', 0);
          expect(countRows()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A2');
          expect(getDataAtCell(0, 1)).toEqual('B2');
          expect(getDataAtCell(1, 0)).toEqual('A1');
          expect(getDataAtCell(1, 1)).toEqual('B1');
          undo();
          expect(countRows()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A3');
          expect(getDataAtCell(0, 1)).toEqual('B3');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A1');
          expect(getDataAtCell(2, 1)).toEqual('B1');
        });
        it('should undo creation of a single column (colHeaders: undefined)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 3)
          });
          expect(countCols()).toEqual(3);
          alter('insert_col');
          expect(countCols()).toEqual(4);
          HOT.undo();
          expect(countCols()).toEqual(3);
        });
        it('should undo creation of a single column (colHeaders: true)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 3),
            colHeaders: true
          });
          expect(countCols()).toEqual(3);
          expect(getColHeader()).toEqual(['A', 'B', 'C']);
          alter('insert_col');
          expect(countCols()).toEqual(4);
          expect(getColHeader()).toEqual(['A', 'B', 'C', 'D']);
          HOT.undo();
          expect(countCols()).toEqual(3);
          expect(getColHeader()).toEqual(['A', 'B', 'C']);
        });
        it('should undo creation of a single column (colHeaders: Array)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 3),
            colHeaders: ['Header1', 'Header2', 'Header3']
          });
          expect(countCols()).toEqual(3);
          expect(getColHeader()).toEqual(['Header1', 'Header2', 'Header3']);
          alter('insert_col', 1);
          expect(countCols()).toEqual(4);
          expect(getColHeader()).toEqual(['Header1', 'B', 'Header2', 'Header3']);
          HOT.undo();
          expect(countCols()).toEqual(3);
          expect(getColHeader()).toEqual(['Header1', 'Header2', 'Header3']);
        });
        it('should undo creation of multiple columns (colHeaders: undefined)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countCols()).toEqual(2);
          alter('insert_col', 1, 5);
          expect(countCols()).toEqual(7);
          HOT.undo();
          expect(countCols()).toEqual(2);
        });
        it('should undo creation of multiple columns (colHeaders: true)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2),
            colHeaders: true
          });
          expect(countCols()).toEqual(2);
          expect(getColHeader()).toEqual(['A', 'B']);
          alter('insert_col', 1, 5);
          expect(countCols()).toEqual(7);
          expect(getColHeader()).toEqual(['A', 'B', 'C', 'D', 'E', 'F', 'G']);
          HOT.undo();
          expect(countCols()).toEqual(2);
          expect(getColHeader()).toEqual(['A', 'B']);
        });
        it('should undo creation of multiple columns (colHeaders: Array)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2),
            colHeaders: ['Header1', 'Header2']
          });
          expect(countCols()).toEqual(2);
          expect(getColHeader()).toEqual(['Header1', 'Header2']);
          alter('insert_col', 1, 5);
          expect(countCols()).toEqual(7);
          expect(getColHeader()).toEqual(['Header1', 'B', 'C', 'D', 'E', 'F', 'Header2']);
          HOT.undo();
          expect(countCols()).toEqual(2);
          expect(getColHeader()).toEqual(['Header1', 'Header2']);
        });
        it('should undo creation of multiple columns with minSpareCols', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(1, 1),
            minSpareCols: 2
          });
          expect(getData()).toEqual([['A1', null, null]]);
          setDataAtCell(0, 1, 'B1');
          setDataAtCell(0, 3, 'C1');
          expect(getData()).toEqual([['A1', 'B1', null, 'C1', null, null]]);
          HOT.undo();
          HOT.undo();
          expect(getData()).toEqual([['A1', null, null]]);
        });
        it('should undo removal of single column (colHeaders: undefined)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 3)
          });
          expect(countCols()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          alter('remove_col', 1);
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('C1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('C2');
          HOT.undo();
          expect(countCols()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
        });
        it('should undo removal of single column (colHeaders: true)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2),
            colHeaders: true
          });
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getColHeader()).toEqual(['A', 'B']);
          alter('remove_col');
          expect(countCols()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toBeNull();
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toBeNull();
          expect(getColHeader()).toEqual(['A']);
          HOT.undo();
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getColHeader()).toEqual(['A', 'B']);
        });
        it('should undo removal of single column (colHeaders: Array)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2),
            colHeaders: ['Header1', 'Header2']
          });
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getColHeader()).toEqual(['Header1', 'Header2']);
          alter('remove_col');
          expect(countCols()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toBeNull();
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toBeNull();
          expect(getColHeader()).toEqual(['Header1']);
          HOT.undo();
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getColHeader()).toEqual(['Header1', 'Header2']);
        });
        it('should undo removal of multiple columns (colHeaders: undefined)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 4)
          });
          expect(countCols()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(0, 3)).toEqual('D1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          expect(getDataAtCell(1, 3)).toEqual('D2');
          alter('remove_col', 1, 2);
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('D1');
          expect(getDataAtCell(0, 2)).toBeNull();
          expect(getDataAtCell(0, 3)).toBeNull();
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('D2');
          expect(getDataAtCell(1, 2)).toBeNull();
          expect(getDataAtCell(1, 3)).toBeNull();
          HOT.undo();
          expect(countCols()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(0, 3)).toEqual('D1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          expect(getDataAtCell(1, 3)).toEqual('D2');
        });
        it('should undo removal of multiple columns (colHeaders: true)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 4),
            colHeaders: true
          });
          expect(countCols()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(0, 3)).toEqual('D1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          expect(getDataAtCell(1, 3)).toEqual('D2');
          expect(getColHeader()).toEqual(['A', 'B', 'C', 'D']);
          alter('remove_col', 1, 3);
          expect(countCols()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toBeNull();
          expect(getDataAtCell(0, 2)).toBeNull();
          expect(getDataAtCell(0, 3)).toBeNull();
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toBeNull();
          expect(getDataAtCell(1, 2)).toBeNull();
          expect(getDataAtCell(1, 3)).toBeNull();
          expect(getColHeader()).toEqual(['A']);
          HOT.undo();
          expect(countCols()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(0, 3)).toEqual('D1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          expect(getDataAtCell(1, 3)).toEqual('D2');
          expect(getColHeader()).toEqual(['A', 'B', 'C', 'D']);
        });
        it('should undo removal of multiple columns (colHeaders: Array)', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 4),
            colHeaders: ['Header1', 'Header2', 'Header3', 'Header4']
          });
          expect(countCols()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(0, 3)).toEqual('D1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          expect(getDataAtCell(1, 3)).toEqual('D2');
          expect(getColHeader()).toEqual(['Header1', 'Header2', 'Header3', 'Header4']);
          alter('remove_col', 1, 2);
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('D1');
          expect(getDataAtCell(0, 2)).toBeNull();
          expect(getDataAtCell(0, 3)).toBeNull();
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('D2');
          expect(getDataAtCell(1, 2)).toBeNull();
          expect(getDataAtCell(1, 3)).toBeNull();
          expect(getColHeader()).toEqual(['Header1', 'Header4']);
          HOT.undo();
          expect(countCols()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(0, 3)).toEqual('D1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          expect(getDataAtCell(1, 3)).toEqual('D2');
          expect(getColHeader()).toEqual(['Header1', 'Header2', 'Header3', 'Header4']);
        });
        it('should undo removal of multiple columns (with a used manualColumnMove)', function () {
          handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 7),
            manualColumnMove: [3, 2, 0, 6, 1, 5, 4]
          });
          expect(countCols()).toEqual(7);
          expect(getDataAtRow(0)).toEqual(['D1', 'C1', 'A1', 'G1', 'B1', 'F1', 'E1']);
          alter('remove_col', 1, 3);
          expect(countCols()).toEqual(4);
          expect(getDataAtRow(0)).toEqual(['D1', 'B1', 'F1', 'E1']); // HOT.undo();
          //
          // expect(countCols()).toEqual(7);
          // expect(getDataAtRow(0)).toEqual(['D1', 'C1', 'A1', 'G1', 'B1', 'F1', 'E1']);
        });
        it('should undo multiple changes', function () {
          handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          var HOT = getInstance();
          setDataAtCell(0, 0, 'X1');
          setDataAtCell(1, 0, 'X2');
          setDataAtCell(0, 1, 'Y1');
          setDataAtCell(1, 1, 'Y2');
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('X2');
          expect(getDataAtCell(0, 1)).toBe('Y1');
          expect(getDataAtCell(1, 1)).toBe('Y2');
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('X2');
          expect(getDataAtCell(0, 1)).toBe('Y1');
          expect(getDataAtCell(1, 1)).toBe('B2');
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('X2');
          expect(getDataAtCell(0, 1)).toBe('B1');
          expect(getDataAtCell(1, 1)).toBe('B2');
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('A2');
          expect(getDataAtCell(0, 1)).toBe('B1');
          expect(getDataAtCell(1, 1)).toBe('B2');
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('A1');
          expect(getDataAtCell(1, 0)).toBe('A2');
          expect(getDataAtCell(0, 1)).toBe('B1');
          expect(getDataAtCell(1, 1)).toBe('B2');
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('A1');
          expect(getDataAtCell(1, 0)).toBe('A2');
          expect(getDataAtCell(0, 1)).toBe('B1');
          expect(getDataAtCell(1, 1)).toBe('B2');
        });
        it('should undo multiple changes in cells with validators', function (done) {
          handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          var HOT = getInstance();
          setDataAtCell(0, 0, 'X1');
          setDataAtCell(1, 0, 'X2');
          setDataAtCell(0, 1, 'Y1');
          setDataAtCell(1, 1, 'Y2');
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('X2');
            expect(getDataAtCell(0, 1)).toBe('Y1');
            expect(getDataAtCell(1, 1)).toBe('Y2');
            HOT.undo();
          }, 200);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('X2');
            expect(getDataAtCell(0, 1)).toBe('Y1');
            expect(getDataAtCell(1, 1)).toBe('B2');
            HOT.undo();
          }, 400);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('X2');
            expect(getDataAtCell(0, 1)).toBe('B1');
            expect(getDataAtCell(1, 1)).toBe('B2');
            HOT.undo();
          }, 600);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('A2');
            expect(getDataAtCell(0, 1)).toBe('B1');
            expect(getDataAtCell(1, 1)).toBe('B2');
            HOT.undo();
          }, 800);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('A1');
            expect(getDataAtCell(1, 0)).toBe('A2');
            expect(getDataAtCell(0, 1)).toBe('B1');
            expect(getDataAtCell(1, 1)).toBe('B2');
            HOT.undo();
          }, 1000);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('A1');
            expect(getDataAtCell(1, 0)).toBe('A2');
            expect(getDataAtCell(0, 1)).toBe('B1');
            expect(getDataAtCell(1, 1)).toBe('B2');
            done();
          }, 1200);
        });
        it('should undo multiple row creations', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row');
          alter('insert_row');
          alter('insert_row');
          alter('insert_row');
          expect(countRows()).toEqual(6);
          HOT.undo();
          expect(countRows()).toEqual(5);
          HOT.undo();
          expect(countRows()).toEqual(4);
          HOT.undo();
          expect(countRows()).toEqual(3);
          HOT.undo();
          expect(countRows()).toEqual(2);
          HOT.undo();
          expect(countRows()).toEqual(2);
        });
        it('should undo multiple row removals', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(4, 2)
          });
          expect(countRows()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          expect(getDataAtCell(3, 0)).toEqual('A4');
          expect(getDataAtCell(3, 1)).toEqual('B4');
          alter('remove_row');
          alter('remove_row');
          alter('remove_row');
          expect(countRows()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          HOT.undo();
          expect(countRows()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          HOT.undo();
          expect(countRows()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          HOT.undo();
          expect(countRows()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          expect(getDataAtCell(3, 0)).toEqual('A4');
          expect(getDataAtCell(3, 1)).toEqual('B4');
          HOT.undo();
          expect(countRows()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          expect(getDataAtCell(3, 0)).toEqual('A4');
          expect(getDataAtCell(3, 1)).toEqual('B4');
        });
        it('should undo changes only for table where the change actually took place', function () {
          spec().$container2 = $("<div id=\"".concat(id, "-2\"></div>")).appendTo('body');
          var hot1 = handsontable({
            data: [[1], [2], [3]]
          });
          spec().$container2.handsontable({
            data: [['A'], ['B'], ['C']]
          });
          var hot2 = spec().$container2.handsontable('getInstance');
          hot1.setDataAtCell(0, 0, 4);
          expect(hot1.getDataAtCell(0, 0)).toEqual(4);
          expect(hot2.getDataAtCell(0, 0)).toEqual('A');
          hot2.undo();
          expect(hot2.getDataAtCell(0, 0)).toEqual('A');
          expect(hot1.getDataAtCell(0, 0)).toEqual(4);
          hot1.undo();
          expect(hot2.getDataAtCell(0, 0)).toEqual('A');
          expect(hot1.getDataAtCell(0, 0)).toEqual(1);
          hot2.destroy();
          spec().$container2.remove();
        });
        it('should return the right amount after undo removal of single column', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 3)
          });
          var afterCreateColCallback = jasmine.createSpy('afterCreateColCallback');
          HOT.addHook('afterCreateCol', afterCreateColCallback);
          expect(countCols()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          alter('remove_col', 1);
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('C1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('C2');
          HOT.undo();
          expect(afterCreateColCallback).toHaveBeenCalledWith(1, 1, 'UndoRedo.undo', void 0, void 0, void 0);
          expect(countCols()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
        });
      });
      describe('redo', function () {
        it('should redo single change', function () {
          handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          var HOT = getInstance();
          setDataAtCell(0, 0, 'new value');
          expect(getDataAtCell(0, 0)).toBe('new value');
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('A1');
          HOT.redo();
          expect(getDataAtCell(0, 0)).toBe('new value');
        });
        it('should redo single change in cell with validator', function (done) {
          handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          var HOT = getInstance();
          setDataAtCell(0, 0, 'new value');
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('new value');
            HOT.undo();
          }, 200);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('A1');
            HOT.redo();
          }, 400);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('new value');
            done();
          }, 600);
        });
        it('should redo creation of a single row', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row');
          expect(countRows()).toEqual(3);
          HOT.undo();
          expect(countRows()).toEqual(2);
          HOT.redo();
          expect(countRows()).toEqual(3);
        });
        it('should redo creation of multiple rows', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row', 0, 5);
          expect(countRows()).toEqual(7);
          HOT.undo();
          expect(countRows()).toEqual(2);
          HOT.redo();
          expect(countRows()).toEqual(7);
        });
        it('should redo removal of single row', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(3, 2)
          });
          expect(countRows()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          alter('remove_row', 1);
          expect(countRows()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A3');
          expect(getDataAtCell(1, 1)).toEqual('B3');
          HOT.undo();
          expect(countRows()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          HOT.redo();
          expect(countRows()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A3');
          expect(getDataAtCell(1, 1)).toEqual('B3');
        });
        it('should redo removal of multiple rows', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(4, 2)
          });
          expect(countRows()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          expect(getDataAtCell(3, 0)).toEqual('A4');
          expect(getDataAtCell(3, 1)).toEqual('B4');
          alter('remove_row', 1, 2);
          expect(countRows()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A4');
          expect(getDataAtCell(1, 1)).toEqual('B4');
          HOT.undo();
          expect(countRows()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          expect(getDataAtCell(3, 0)).toEqual('A4');
          expect(getDataAtCell(3, 1)).toEqual('B4');
          HOT.redo();
          expect(countRows()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A4');
          expect(getDataAtCell(1, 1)).toEqual('B4');
        });
        it('should redo creation of a single column', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countCols()).toEqual(2);
          alter('insert_col');
          expect(countCols()).toEqual(3);
          HOT.undo();
          expect(countCols()).toEqual(2);
          HOT.redo();
          expect(countCols()).toEqual(3);
        });
        it('should redo creation of multiple columns', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countCols()).toEqual(2);
          alter('insert_col', 1, 5);
          expect(countCols()).toEqual(7);
          HOT.undo();
          expect(countCols()).toEqual(2);
          HOT.redo();
          expect(countCols()).toEqual(7);
        });
        it('should redo removal of single column', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          alter('remove_col');
          expect(countCols()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toBeNull();
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toBeNull();
          HOT.undo();
          expect(countCols()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          HOT.redo();
          expect(countCols()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toBeNull();
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toBeNull();
        });
        it('should redo removal of multiple columns', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 4)
          });
          expect(countCols()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(0, 3)).toEqual('D1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          expect(getDataAtCell(1, 3)).toEqual('D2');
          alter('remove_col', 1, 3);
          expect(countCols()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toBeNull();
          expect(getDataAtCell(0, 2)).toBeNull();
          expect(getDataAtCell(0, 3)).toBeNull();
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toBeNull();
          expect(getDataAtCell(1, 2)).toBeNull();
          expect(getDataAtCell(1, 3)).toBeNull();
          HOT.undo();
          expect(countCols()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(0, 2)).toEqual('C1');
          expect(getDataAtCell(0, 3)).toEqual('D1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(1, 2)).toEqual('C2');
          expect(getDataAtCell(1, 3)).toEqual('D2');
          HOT.redo();
          expect(countCols()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toBeNull();
          expect(getDataAtCell(0, 2)).toBeNull();
          expect(getDataAtCell(0, 3)).toBeNull();
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toBeNull();
          expect(getDataAtCell(1, 2)).toBeNull();
          expect(getDataAtCell(1, 3)).toBeNull();
        });
        it('should redo multiple changes', function () {
          handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          var HOT = getInstance();
          setDataAtCell(0, 0, 'X1');
          setDataAtCell(1, 0, 'X2');
          setDataAtCell(0, 1, 'Y1');
          setDataAtCell(1, 1, 'Y2');
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('X2');
          expect(getDataAtCell(0, 1)).toBe('Y1');
          expect(getDataAtCell(1, 1)).toBe('Y2');
          HOT.undo();
          HOT.undo();
          HOT.undo();
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('A1');
          expect(getDataAtCell(1, 0)).toBe('A2');
          expect(getDataAtCell(0, 1)).toBe('B1');
          expect(getDataAtCell(1, 1)).toBe('B2');
          HOT.redo();
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('A2');
          expect(getDataAtCell(0, 1)).toBe('B1');
          expect(getDataAtCell(1, 1)).toBe('B2');
          HOT.redo();
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('X2');
          expect(getDataAtCell(0, 1)).toBe('B1');
          expect(getDataAtCell(1, 1)).toBe('B2');
          HOT.redo();
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('X2');
          expect(getDataAtCell(0, 1)).toBe('Y1');
          expect(getDataAtCell(1, 1)).toBe('B2');
          HOT.redo();
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('X2');
          expect(getDataAtCell(0, 1)).toBe('Y1');
          expect(getDataAtCell(1, 1)).toBe('Y2');
          HOT.redo();
          expect(getDataAtCell(0, 0)).toBe('X1');
          expect(getDataAtCell(1, 0)).toBe('X2');
          expect(getDataAtCell(0, 1)).toBe('Y1');
          expect(getDataAtCell(1, 1)).toBe('Y2');
        });
        it('should redo multiple changes in cell with validator', function (done) {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          setDataAtCell(0, 0, 'X1');
          setDataAtCell(1, 0, 'X2');
          setDataAtCell(0, 1, 'Y1');
          setDataAtCell(1, 1, 'Y2');
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('X2');
            expect(getDataAtCell(0, 1)).toBe('Y1');
            expect(getDataAtCell(1, 1)).toBe('Y2');
            HOT.undo();
          }, 200);
          setTimeout(function () {
            HOT.undo();
          }, 400);
          setTimeout(function () {
            HOT.undo();
          }, 600);
          setTimeout(function () {
            HOT.undo();
          }, 800);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('A1');
            expect(getDataAtCell(1, 0)).toBe('A2');
            expect(getDataAtCell(0, 1)).toBe('B1');
            expect(getDataAtCell(1, 1)).toBe('B2');
            HOT.redo();
          }, 1000);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('A2');
            expect(getDataAtCell(0, 1)).toBe('B1');
            expect(getDataAtCell(1, 1)).toBe('B2');
            HOT.redo();
          }, 1200);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('X2');
            expect(getDataAtCell(0, 1)).toBe('B1');
            expect(getDataAtCell(1, 1)).toBe('B2');
            HOT.redo();
          }, 1400);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('X2');
            expect(getDataAtCell(0, 1)).toBe('Y1');
            expect(getDataAtCell(1, 1)).toBe('B2');
            HOT.redo();
          }, 1600);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('X2');
            expect(getDataAtCell(0, 1)).toBe('Y1');
            expect(getDataAtCell(1, 1)).toBe('Y2');
            HOT.redo();
          }, 1800);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('X1');
            expect(getDataAtCell(1, 0)).toBe('X2');
            expect(getDataAtCell(0, 1)).toBe('Y1');
            expect(getDataAtCell(1, 1)).toBe('Y2');
            done();
          }, 2000);
        });
        it('should redo multiple row creations', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(2, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row');
          alter('insert_row');
          alter('insert_row');
          alter('insert_row');
          expect(countRows()).toEqual(6);
          HOT.undo();
          HOT.undo();
          HOT.undo();
          HOT.undo();
          expect(countRows()).toEqual(2);
          HOT.redo();
          expect(countRows()).toEqual(3);
          HOT.redo();
          expect(countRows()).toEqual(4);
          HOT.redo();
          expect(countRows()).toEqual(5);
          HOT.redo();
          expect(countRows()).toEqual(6);
          HOT.redo();
          expect(countRows()).toEqual(6);
        });
        it('should undo multiple row removals', function () {
          var HOT = handsontable({
            data: Handsontable.helper.createSpreadsheetData(4, 2)
          });
          expect(countRows()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          expect(getDataAtCell(3, 0)).toEqual('A4');
          expect(getDataAtCell(3, 1)).toEqual('B4');
          alter('remove_row');
          alter('remove_row');
          alter('remove_row');
          expect(countRows()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          HOT.undo();
          HOT.undo();
          HOT.undo();
          expect(countRows()).toEqual(4);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          expect(getDataAtCell(3, 0)).toEqual('A4');
          expect(getDataAtCell(3, 1)).toEqual('B4');
          HOT.redo();
          expect(countRows()).toEqual(3);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          expect(getDataAtCell(2, 0)).toEqual('A3');
          expect(getDataAtCell(2, 1)).toEqual('B3');
          HOT.redo();
          expect(countRows()).toEqual(2);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          expect(getDataAtCell(1, 0)).toEqual('A2');
          expect(getDataAtCell(1, 1)).toEqual('B2');
          HOT.redo();
          expect(countRows()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
          HOT.redo();
          expect(countRows()).toEqual(1);
          expect(getDataAtCell(0, 0)).toEqual('A1');
          expect(getDataAtCell(0, 1)).toEqual('B1');
        });
        it('should redo changes only for table where the change actually took place', function () {
          spec().$container2 = $("<div id=\"".concat(id, "-2\"></div>")).appendTo('body');
          var hot1 = handsontable({
            data: [[1], [2], [3]]
          });
          spec().$container2.handsontable({
            data: [['A'], ['B'], ['C']]
          });
          var hot2 = spec().$container2.handsontable('getInstance');
          hot1.setDataAtCell(0, 0, 4);
          expect(hot1.getDataAtCell(0, 0)).toEqual(4);
          expect(hot2.getDataAtCell(0, 0)).toEqual('A');
          hot1.undo();
          expect(hot1.getDataAtCell(0, 0)).toEqual(1);
          expect(hot2.getDataAtCell(0, 0)).toEqual('A');
          hot2.redo();
          expect(hot1.getDataAtCell(0, 0)).toEqual(1);
          expect(hot2.getDataAtCell(0, 0)).toEqual('A');
          hot1.redo();
          expect(hot1.getDataAtCell(0, 0)).toEqual(4);
          expect(hot2.getDataAtCell(0, 0)).toEqual('A');
          hot2.destroy();
          spec().$container2.remove();
        });
      });
    });
    describe('Object data', function () {
      function createObjectData() {
        return [{
          name: 'Timothy',
          surname: 'Dalton'
        }, {
          name: 'Sean',
          surname: 'Connery'
        }, {
          name: 'Roger',
          surname: 'Moore'
        }];
      }

      describe('undo', function () {
        it('should undo single change', function () {
          handsontable({
            data: createObjectData()
          });
          var HOT = getInstance();
          setDataAtRowProp(0, 0, 'Pearce');
          expect(getDataAtRowProp(0, 0)).toBe('Pearce');
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('Timothy');
        });
        it('should undo single change in cell with validator', function (done) {
          handsontable({
            data: createObjectData()
          });
          var HOT = getInstance();
          setDataAtRowProp(0, 0, 'Pearce');
          setTimeout(function () {
            expect(getDataAtRowProp(0, 0)).toBe('Pearce');
            HOT.undo();
          }, 200);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('Timothy');
            done();
          }, 400);
        });
        it('should undo creation of a single row', function () {
          var HOT = handsontable({
            data: createObjectData().slice(0, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row');
          expect(countRows()).toEqual(3);
          HOT.undo();
          expect(countRows()).toEqual(2);
        });
        it('should undo creation of multiple rows', function () {
          var HOT = handsontable({
            data: createObjectData().slice(0, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row', 0, 5);
          expect(countRows()).toEqual(7);
          HOT.undo();
          expect(countRows()).toEqual(2);
        });
        it('should undo removal of single row', function () {
          var HOT = handsontable({
            data: createObjectData().slice(0, 2)
          });
          expect(countRows()).toEqual(2);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          alter('remove_row');
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBeNull();
          expect(getDataAtRowProp(1, 'surname')).toBeNull();
          HOT.undo();
          expect(countRows()).toEqual(2);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
        });
        it('should undo removal of multiple rows', function () {
          var HOT = handsontable({
            data: createObjectData()
          });
          expect(countRows()).toEqual(3);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          expect(getDataAtRowProp(2, 'name')).toEqual('Roger');
          expect(getDataAtRowProp(2, 'surname')).toEqual('Moore');
          alter('remove_row', 1, 2);
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBeNull();
          expect(getDataAtRowProp(1, 'surname')).toBeNull();
          expect(getDataAtRowProp(2, 'name')).toBeNull();
          expect(getDataAtRowProp(2, 'surname')).toBeNull();
          HOT.undo();
          expect(countRows()).toEqual(3);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          expect(getDataAtRowProp(2, 'name')).toEqual('Roger');
          expect(getDataAtRowProp(2, 'surname')).toEqual('Moore');
        });
        it('should undo multiple changes', function () {
          handsontable({
            data: createObjectData().slice(0, 2)
          });
          var HOT = getInstance();
          setDataAtRowProp(0, 'name', 'Pierce');
          setDataAtRowProp(0, 'surname', 'Brosnan');
          setDataAtRowProp(1, 'name', 'Daniel');
          setDataAtRowProp(1, 'surname', 'Craig');
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
          expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
          expect(getDataAtRowProp(1, 'surname')).toBe('Craig');
          HOT.undo();
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
          expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
          expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
          HOT.undo();
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
          expect(getDataAtRowProp(1, 'name')).toBe('Sean');
          expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
          HOT.undo();
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBe('Sean');
          expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
          HOT.undo();
          expect(getDataAtRowProp(0, 'name')).toBe('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBe('Sean');
          expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
          HOT.undo();
          expect(getDataAtRowProp(0, 'name')).toBe('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBe('Sean');
          expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
        });
        it('should undo multiple changes in cells with validators', function (done) {
          handsontable({
            data: createObjectData().slice(0, 2)
          });
          var HOT = getInstance();
          setDataAtRowProp(0, 'name', 'Pierce');
          setDataAtRowProp(0, 'surname', 'Brosnan');
          setDataAtRowProp(1, 'name', 'Daniel');
          setDataAtRowProp(1, 'surname', 'Craig');
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
            expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
            expect(getDataAtRowProp(1, 'surname')).toBe('Craig');
            HOT.undo();
          }, 200);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
            expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
            expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
            HOT.undo();
          }, 400);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
            expect(getDataAtRowProp(1, 'name')).toBe('Sean');
            expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
            HOT.undo();
          }, 600);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
            expect(getDataAtRowProp(1, 'name')).toBe('Sean');
            expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
            HOT.undo();
          }, 800);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Timothy');
            expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
            expect(getDataAtRowProp(1, 'name')).toBe('Sean');
            expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
            HOT.undo();
          }, 1000);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Timothy');
            expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
            expect(getDataAtRowProp(1, 'name')).toBe('Sean');
            expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
            done();
          }, 1200);
        });
        it('should undo multiple row creations', function () {
          var HOT = handsontable({
            data: createObjectData().slice(0, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row');
          alter('insert_row');
          alter('insert_row');
          alter('insert_row');
          expect(countRows()).toEqual(6);
          HOT.undo();
          expect(countRows()).toEqual(5);
          HOT.undo();
          expect(countRows()).toEqual(4);
          HOT.undo();
          expect(countRows()).toEqual(3);
          HOT.undo();
          expect(countRows()).toEqual(2);
          HOT.undo();
          expect(countRows()).toEqual(2);
        });
        it('should undo multiple row removals', function () {
          var HOT = handsontable({
            data: createObjectData()
          });
          expect(countRows()).toEqual(3);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          expect(getDataAtRowProp(2, 'name')).toEqual('Roger');
          expect(getDataAtRowProp(2, 'surname')).toEqual('Moore');
          alter('remove_row');
          alter('remove_row');
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          HOT.undo();
          expect(countRows()).toEqual(2);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          HOT.undo();
          expect(countRows()).toEqual(3);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          expect(getDataAtRowProp(2, 'name')).toEqual('Roger');
          expect(getDataAtRowProp(2, 'surname')).toEqual('Moore');
          HOT.undo();
          expect(countRows()).toEqual(3);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          expect(getDataAtRowProp(2, 'name')).toEqual('Roger');
          expect(getDataAtRowProp(2, 'surname')).toEqual('Moore');
        });
      });
      describe('redo', function () {
        it('should redo single change', function () {
          handsontable({
            data: createObjectData()
          });
          var HOT = getInstance();
          setDataAtRowProp(0, 0, 'Pearce');
          expect(getDataAtRowProp(0, 0)).toBe('Pearce');
          HOT.undo();
          expect(getDataAtCell(0, 0)).toBe('Timothy');
          HOT.redo();
          expect(getDataAtRowProp(0, 0)).toBe('Pearce');
        });
        it('should redo single change in cell with validator', function (done) {
          handsontable({
            data: createObjectData()
          });
          var HOT = getInstance();
          setDataAtRowProp(0, 0, 'Pearce');
          setTimeout(function () {
            expect(getDataAtRowProp(0, 0)).toBe('Pearce');
            HOT.undo();
          }, 200);
          setTimeout(function () {
            expect(getDataAtCell(0, 0)).toBe('Timothy');
            HOT.redo();
          }, 400);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 0)).toBe('Pearce');
            done();
          }, 600);
        });
        it('should redo creation of a single row', function () {
          var HOT = handsontable({
            data: createObjectData().slice(0, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row');
          expect(countRows()).toEqual(3);
          HOT.undo();
          expect(countRows()).toEqual(2);
          HOT.redo();
          expect(countRows()).toEqual(3);
        });
        it('should redo creation of multiple rows', function () {
          var HOT = handsontable({
            data: createObjectData().slice(0, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row', 0, 5);
          expect(countRows()).toEqual(7);
          HOT.undo();
          expect(countRows()).toEqual(2);
          HOT.redo();
          expect(countRows()).toEqual(7);
        });
        it('should redo removal of single row', function () {
          var HOT = handsontable({
            data: createObjectData().slice(0, 2)
          });
          expect(countRows()).toEqual(2);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          alter('remove_row');
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBeNull();
          expect(getDataAtRowProp(1, 'surname')).toBeNull();
          HOT.undo();
          expect(countRows()).toEqual(2);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          HOT.redo();
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBeNull();
          expect(getDataAtRowProp(1, 'surname')).toBeNull();
        });
        it('should redo removal of multiple rows', function () {
          var HOT = handsontable({
            data: createObjectData()
          });
          expect(countRows()).toEqual(3);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          expect(getDataAtRowProp(2, 'name')).toEqual('Roger');
          expect(getDataAtRowProp(2, 'surname')).toEqual('Moore');
          alter('remove_row', 1, 2);
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBeNull();
          expect(getDataAtRowProp(1, 'surname')).toBeNull();
          expect(getDataAtRowProp(2, 'name')).toBeNull();
          expect(getDataAtRowProp(2, 'surname')).toBeNull();
          HOT.undo();
          expect(countRows()).toEqual(3);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          expect(getDataAtRowProp(2, 'name')).toEqual('Roger');
          expect(getDataAtRowProp(2, 'surname')).toEqual('Moore');
          HOT.redo();
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBeNull();
          expect(getDataAtRowProp(1, 'surname')).toBeNull();
          expect(getDataAtRowProp(2, 'name')).toBeNull();
          expect(getDataAtRowProp(2, 'surname')).toBeNull();
        });
        it('should redo multiple changes', function () {
          handsontable({
            data: createObjectData().slice(0, 2)
          });
          var HOT = getInstance();
          setDataAtRowProp(0, 'name', 'Pierce');
          setDataAtRowProp(0, 'surname', 'Brosnan');
          setDataAtRowProp(1, 'name', 'Daniel');
          setDataAtRowProp(1, 'surname', 'Craig');
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
          expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
          expect(getDataAtRowProp(1, 'surname')).toBe('Craig');
          HOT.undo();
          HOT.undo();
          HOT.undo();
          HOT.undo();
          expect(getDataAtRowProp(0, 'name')).toBe('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBe('Sean');
          expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
          HOT.redo();
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
          expect(getDataAtRowProp(1, 'name')).toBe('Sean');
          expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
          HOT.redo();
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
          expect(getDataAtRowProp(1, 'name')).toBe('Sean');
          expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
          HOT.redo();
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
          expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
          expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
          HOT.redo();
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
          expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
          expect(getDataAtRowProp(1, 'surname')).toBe('Craig');
          HOT.redo();
          expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
          expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
          expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
          expect(getDataAtRowProp(1, 'surname')).toBe('Craig');
        });
        it('should redo multiple changes in cells with validators', function (done) {
          handsontable({
            data: createObjectData().slice(0, 2)
          });
          var HOT = getInstance();
          setDataAtRowProp(0, 'name', 'Pierce');
          setDataAtRowProp(0, 'surname', 'Brosnan');
          setDataAtRowProp(1, 'name', 'Daniel');
          setDataAtRowProp(1, 'surname', 'Craig');
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
            expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
            expect(getDataAtRowProp(1, 'surname')).toBe('Craig');
            HOT.undo();
          }, 200);
          setTimeout(function () {
            HOT.undo();
          }, 400);
          setTimeout(function () {
            HOT.undo();
          }, 600);
          setTimeout(function () {
            HOT.undo();
          }, 800);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Timothy');
            expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
            expect(getDataAtRowProp(1, 'name')).toBe('Sean');
            expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
            HOT.redo();
          }, 1000);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Dalton');
            expect(getDataAtRowProp(1, 'name')).toBe('Sean');
            expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
            HOT.redo();
          }, 1200);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
            expect(getDataAtRowProp(1, 'name')).toBe('Sean');
            expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
            HOT.redo();
          }, 1400);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
            expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
            expect(getDataAtRowProp(1, 'surname')).toBe('Connery');
            HOT.redo();
          }, 1600);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
            expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
            expect(getDataAtRowProp(1, 'surname')).toBe('Craig');
            HOT.redo();
          }, 1800);
          setTimeout(function () {
            expect(getDataAtRowProp(0, 'name')).toBe('Pierce');
            expect(getDataAtRowProp(0, 'surname')).toBe('Brosnan');
            expect(getDataAtRowProp(1, 'name')).toBe('Daniel');
            expect(getDataAtRowProp(1, 'surname')).toBe('Craig');
            done();
          }, 2000);
        });
        it('should redo multiple row creations', function () {
          var HOT = handsontable({
            data: createObjectData().slice(0, 2)
          });
          expect(countRows()).toEqual(2);
          alter('insert_row');
          alter('insert_row');
          alter('insert_row');
          alter('insert_row');
          expect(countRows()).toEqual(6);
          HOT.undo();
          HOT.undo();
          HOT.undo();
          HOT.undo();
          expect(countRows()).toEqual(2);
          HOT.redo();
          expect(countRows()).toEqual(3);
          HOT.redo();
          expect(countRows()).toEqual(4);
          HOT.redo();
          expect(countRows()).toEqual(5);
          HOT.redo();
          expect(countRows()).toEqual(6);
          HOT.redo();
          expect(countRows()).toEqual(6);
        });
        it('should undo multiple row removals', function () {
          var HOT = handsontable({
            data: createObjectData()
          });
          expect(countRows()).toEqual(3);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          expect(getDataAtRowProp(2, 'name')).toEqual('Roger');
          expect(getDataAtRowProp(2, 'surname')).toEqual('Moore');
          alter('remove_row');
          alter('remove_row');
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          HOT.undo();
          HOT.undo();
          HOT.undo();
          expect(countRows()).toEqual(3);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          expect(getDataAtRowProp(2, 'name')).toEqual('Roger');
          expect(getDataAtRowProp(2, 'surname')).toEqual('Moore');
          HOT.redo();
          expect(countRows()).toEqual(2);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          expect(getDataAtRowProp(1, 'name')).toEqual('Sean');
          expect(getDataAtRowProp(1, 'surname')).toEqual('Connery');
          HOT.redo();
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
          HOT.redo();
          expect(countRows()).toEqual(1);
          expect(getDataAtRowProp(0, 'name')).toEqual('Timothy');
          expect(getDataAtRowProp(0, 'surname')).toEqual('Dalton');
        });
      });
    });
  });
  describe('plugin features', function () {
    describe('cell alignment', function () {
      it('should undo a sequence of aligning cells', function () {
        var hot = handsontable({
          data: Handsontable.helper.createSpreadsheetData(9, 9),
          contextMenu: true,
          colWidths: [50, 50, 50, 50, 50, 50, 50, 50, 50],
          rowHeights: [50, 50, 50, 50, 50, 50, 50, 50, 50]
        }); // top 3 rows center

        selectCell(0, 0, 2, 8);
        hot.getPlugin('contextMenu').executeCommand('alignment:center'); // middle 3 rows unchanged - left
        // bottom 3 rows right

        selectCell(6, 0, 8, 8);
        hot.getPlugin('contextMenu').executeCommand('alignment:right'); // left 3 columns - middle

        selectCell(0, 0, 8, 2);
        hot.getPlugin('contextMenu').executeCommand('alignment:middle'); // middle 3 columns unchanged - top
        // right 3 columns - bottom

        selectCell(0, 6, 8, 8);
        hot.getPlugin('contextMenu').executeCommand('alignment:bottom');
        var cellMeta = hot.getCellMeta(0, 0);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htMiddle')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(0, 7);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htBottom')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(5, 1);
        expect(cellMeta.className.indexOf('htMiddle')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(5, 7);
        expect(cellMeta.className.indexOf('htBottom')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(7, 1);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htMiddle')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(7, 5);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(7, 7);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htBottom')).toBeGreaterThan(-1);
        hot.undo();
        cellMeta = hot.getCellMeta(0, 7);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htBottom')).toEqual(-1);
        cellMeta = hot.getCellMeta(5, 7);
        expect(cellMeta.className.indexOf('htBottom')).toEqual(-1);
        cellMeta = hot.getCellMeta(7, 7);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htBottom')).toEqual(-1);
        hot.undo();
        cellMeta = hot.getCellMeta(0, 0);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htMiddle')).toEqual(-1);
        cellMeta = hot.getCellMeta(5, 1);
        expect(cellMeta.className.indexOf('htMiddle')).toEqual(-1);
        cellMeta = hot.getCellMeta(7, 1);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htMiddle')).toEqual(-1);
        hot.undo();
        cellMeta = hot.getCellMeta(7, 1);
        expect(cellMeta.className.indexOf('htRight')).toEqual(-1);
        expect(cellMeta.className.indexOf('htMiddle')).toEqual(-1);
        cellMeta = hot.getCellMeta(7, 5);
        expect(cellMeta.className.indexOf('htRight')).toEqual(-1);
        cellMeta = hot.getCellMeta(7, 7);
        expect(cellMeta.className.indexOf('htRight')).toEqual(-1);
        expect(cellMeta.className.indexOf('htBottom')).toEqual(-1);
        hot.undo(); // check if all cells are either non-adjusted or adjusted to the left (as default)

        var finish;

        for (var i = 0; i < 9; i++) {
          for (var j = 0; j < 9; j++) {
            cellMeta = hot.getCellMeta(i, j);
            finish = cellMeta.className === void 0 || cellMeta.className.trim() === '' || cellMeta.className.trim() === 'htLeft';
            expect(finish).toBe(true);
          }
        }
      });
      it('should redo a sequence of aligning cells', function () {
        var hot = handsontable({
          data: Handsontable.helper.createSpreadsheetData(9, 9),
          contextMenu: true,
          colWidths: [50, 50, 50, 50, 50, 50, 50, 50, 50],
          rowHeights: [50, 50, 50, 50, 50, 50, 50, 50, 50]
        }); // top 3 rows center

        selectCell(0, 0, 2, 8);
        hot.getPlugin('contextMenu').executeCommand('alignment:center'); // middle 3 rows unchanged - left
        // bottom 3 rows right

        selectCell(6, 0, 8, 8);
        hot.getPlugin('contextMenu').executeCommand('alignment:right'); // left 3 columns - middle

        selectCell(0, 0, 8, 2);
        hot.getPlugin('contextMenu').executeCommand('alignment:middle'); // middle 3 columns unchanged - top
        // right 3 columns - bottom

        selectCell(0, 6, 8, 8);
        hot.getPlugin('contextMenu').executeCommand('alignment:bottom');
        var cellMeta = hot.getCellMeta(0, 0);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htMiddle')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(0, 7);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htBottom')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(5, 1);
        expect(cellMeta.className.indexOf('htMiddle')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(5, 7);
        expect(cellMeta.className.indexOf('htBottom')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(7, 1);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htMiddle')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(7, 5);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(7, 7);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htBottom')).toBeGreaterThan(-1);
        hot.undo();
        hot.undo();
        hot.undo();
        hot.undo(); // check if all cells are either non-adjusted or adjusted to the left (as default)

        var finish;

        for (var i = 0; i < 9; i++) {
          for (var j = 0; j < 9; j++) {
            cellMeta = hot.getCellMeta(i, j);
            finish = cellMeta.className === void 0 || cellMeta.className.trim() === '' || cellMeta.className.trim() === 'htLeft';
            expect(finish).toBe(true);
          }
        }

        hot.redo();
        cellMeta = hot.getCellMeta(0, 0);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(1, 5);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(2, 8);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        hot.redo();
        cellMeta = hot.getCellMeta(6, 0);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(7, 5);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(8, 8);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        hot.redo();
        cellMeta = hot.getCellMeta(0, 0);
        expect(cellMeta.className.indexOf('htMiddle')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(5, 1);
        expect(cellMeta.className.indexOf('htMiddle')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(8, 2);
        expect(cellMeta.className.indexOf('htMiddle')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
        hot.redo();
        cellMeta = hot.getCellMeta(0, 6);
        expect(cellMeta.className.indexOf('htBottom')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htCenter')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(5, 7);
        expect(cellMeta.className.indexOf('htBottom')).toBeGreaterThan(-1);
        cellMeta = hot.getCellMeta(8, 8);
        expect(cellMeta.className.indexOf('htBottom')).toBeGreaterThan(-1);
        expect(cellMeta.className.indexOf('htRight')).toBeGreaterThan(-1);
      });
    });
    it('should exposed new methods when plugin is enabled', function () {
      var hot = handsontable({
        undo: false
      });
      expect(hot.undo).toBeUndefined();
      expect(hot.redo).toBeUndefined();
      expect(hot.isUndoAvailable).toBeUndefined();
      expect(hot.isRedoAvailable).toBeUndefined();
      expect(hot.clearUndo).toBeUndefined();
      updateSettings({
        undo: true
      });
      expect(_typeof(hot.undo)).toEqual('function');
      expect(_typeof(hot.redo)).toEqual('function');
      expect(_typeof(hot.isUndoAvailable)).toEqual('function');
      expect(_typeof(hot.isRedoAvailable)).toEqual('function');
      expect(_typeof(hot.clearUndo)).toEqual('function');
    });
    it('should remove exposed methods when plugin is disbaled', function () {
      var hot = handsontable({
        undo: true
      });
      expect(_typeof(hot.undo)).toEqual('function');
      expect(_typeof(hot.redo)).toEqual('function');
      expect(_typeof(hot.isUndoAvailable)).toEqual('function');
      expect(_typeof(hot.isRedoAvailable)).toEqual('function');
      expect(_typeof(hot.clearUndo)).toEqual('function');
      updateSettings({
        undo: false
      });
      expect(hot.undo).toBeUndefined();
      expect(hot.redo).toBeUndefined();
      expect(hot.isUndoAvailable).toBeUndefined();
      expect(hot.isRedoAvailable).toBeUndefined();
      expect(hot.clearUndo).toBeUndefined();
    });
    describe('Keyboard shortcuts', function () {
      it('should undo single change after hitting CTRL+Z', function () {
        handsontable({
          data: Handsontable.helper.createSpreadsheetData(2, 2)
        });
        selectCell(0, 0);
        setDataAtCell(0, 0, 'new value');
        spec().$container.simulate('keydown', {
          ctrlKey: true,
          keyCode: 'Z'.charCodeAt(0)
        });
        expect(getDataAtCell(0, 0)).toBe('A1');
      });
      it('should redo single change after hitting CTRL+Y', function () {
        handsontable({
          data: Handsontable.helper.createSpreadsheetData(2, 2)
        });
        var HOT = getInstance();
        selectCell(0, 0);
        setDataAtCell(0, 0, 'new value');
        expect(getDataAtCell(0, 0)).toBe('new value');
        HOT.undo();
        expect(getDataAtCell(0, 0)).toBe('A1');
        spec().$container.simulate('keydown', {
          ctrlKey: true,
          keyCode: 'Y'.charCodeAt(0)
        });
        expect(getDataAtCell(0, 0)).toBe('new value');
      });
      it('should redo single change after hitting CTRL+SHIFT+Z', function () {
        handsontable({
          data: Handsontable.helper.createSpreadsheetData(2, 2)
        });
        var HOT = getInstance();
        selectCell(0, 0);
        setDataAtCell(0, 0, 'new value');
        expect(getDataAtCell(0, 0)).toBe('new value');
        HOT.undo();
        expect(getDataAtCell(0, 0)).toBe('A1');
        spec().$container.simulate('keydown', {
          ctrlKey: true,
          shiftKey: true,
          keyCode: 'Z'.charCodeAt(0)
        });
        expect(getDataAtCell(0, 0)).toBe('new value');
      });
    });
  });
  describe('Hooks', function () {
    it('should fire a `beforeUndo` hook after the undo process begins', function (done) {
      var beforeUndoSpy = jasmine.createSpy('beforeUndo');
      var hot = handsontable({
        data: Handsontable.helper.createSpreadsheetData(2, 2)
      });
      var hookData = null;
      hot.addHook('beforeUndo', beforeUndoSpy);
      hot.addHook('beforeUndo', function (data) {
        hookData = data;
      });
      alter('remove_row', 1);
      setTimeout(function () {
        hot.undo();
      }, 10);
      setTimeout(function () {
        expect(beforeUndoSpy.calls.count()).toEqual(1);
        expect(hookData).not.toBe(null);
        expect(hookData.actionType).toEqual('remove_row');
        expect(hookData.data).toEqual([['A2', 'B2']]);
        done();
      }, 100);
    });
    it('should fire a `beforeRedo` hook before the redo process begins', function (done) {
      var beforeRedoSpy = jasmine.createSpy('beforeRedo');
      var hot = handsontable({
        data: Handsontable.helper.createSpreadsheetData(2, 2)
      });
      var hookData = null;
      hot.addHook('beforeRedo', beforeRedoSpy);
      hot.addHook('beforeRedo', function (data) {
        hookData = data;
      });
      alter('remove_row', 1);
      setTimeout(function () {
        hot.undo();
        hot.redo();
      }, 10);
      setTimeout(function () {
        expect(beforeRedoSpy.calls.count()).toEqual(1);
        expect(hookData).not.toBe(null);
        expect(hookData.actionType).toEqual('remove_row');
        expect(hookData.data).toEqual([['A2', 'B2']]);
        done();
      }, 100);
    });
    it('should fire a `afterRedo` hook after the redo process begins', function (done) {
      var afterRedoSpy = jasmine.createSpy('afterRedo');
      var hot = handsontable({
        data: Handsontable.helper.createSpreadsheetData(2, 2)
      });
      var hookData = null;
      hot.addHook('beforeRedo', afterRedoSpy);
      hot.addHook('beforeRedo', function (data) {
        hookData = data;
      });
      alter('remove_row', 1);
      setTimeout(function () {
        hot.undo();
        hot.redo();
      }, 10);
      setTimeout(function () {
        expect(afterRedoSpy.calls.count()).toEqual(1);
        expect(hookData).not.toBe(null);
        expect(hookData.actionType).toEqual('remove_row');
        expect(hookData.data).toEqual([['A2', 'B2']]);
        done();
      }, 100);
    });
  });
});