import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _extends from "@babel/runtime/helpers/extends";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

import * as React from 'react';
import { findDOMNode } from 'react-dom';
import { Simulate } from 'react-dom/test-utils';
import TestRenderer from 'react-test-renderer';
import { render } from '../TestUtils';
import Grid, { DEFAULT_SCROLLING_RESET_TIME_INTERVAL } from './Grid';
import defaultCellRangeRenderer from './defaultCellRangeRenderer';
import { CellMeasurer, CellMeasurerCache } from '../CellMeasurer';
import { SCROLL_DIRECTION_BACKWARD, SCROLL_DIRECTION_FORWARD } from './defaultOverscanIndicesGetter';
import { getMaxElementSize } from './utils/maxElementSize.js';
var DEFAULT_COLUMN_WIDTH = 50;
var DEFAULT_HEIGHT = 100;
var DEFAULT_ROW_HEIGHT = 20;
var DEFAULT_WIDTH = 200;
var NUM_ROWS = 100;
var NUM_COLUMNS = 50;

function getScrollbarSize0() {
  return 0;
}

function getScrollbarSize20() {
  return 20;
}

describe('Grid', function () {
  function defaultCellRenderer(_ref) {
    var columnIndex = _ref.columnIndex,
        key = _ref.key,
        rowIndex = _ref.rowIndex,
        style = _ref.style;
    return React.createElement("div", {
      className: "gridItem",
      key: key,
      style: style
    }, "row:".concat(rowIndex, ", column:").concat(columnIndex));
  }

  function simulateScroll(_ref2) {
    var grid = _ref2.grid,
        _ref2$scrollLeft = _ref2.scrollLeft,
        scrollLeft = _ref2$scrollLeft === void 0 ? 0 : _ref2$scrollLeft,
        _ref2$scrollTop = _ref2.scrollTop,
        scrollTop = _ref2$scrollTop === void 0 ? 0 : _ref2$scrollTop;
    var target = {
      scrollLeft: scrollLeft,
      scrollTop: scrollTop
    };
    grid._scrollingContainer = target; // HACK to work around _onScroll target check

    Simulate.scroll(findDOMNode(grid), {
      target: target
    });
  }

  function getMarkup() {
    var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    return React.createElement(Grid, _extends({
      cellRenderer: defaultCellRenderer,
      columnCount: NUM_COLUMNS,
      columnWidth: DEFAULT_COLUMN_WIDTH,
      getScrollbarSize: getScrollbarSize0,
      height: DEFAULT_HEIGHT,
      overscanColumnCount: 0,
      overscanRowCount: 0,
      autoHeight: false,
      rowHeight: DEFAULT_ROW_HEIGHT,
      rowCount: NUM_ROWS,
      width: DEFAULT_WIDTH
    }, props));
  }

  describe('number of rendered children', function () {
    it('should render enough children to fill the available area', function () {
      var rendered = findDOMNode(render(getMarkup()));
      expect(rendered.querySelectorAll('.gridItem').length).toEqual(20); // 5 rows x 4 columns
    });
    it('should not render more rows than available if the area is not filled', function () {
      var rendered = findDOMNode(render(getMarkup({
        rowCount: 2
      })));
      expect(rendered.querySelectorAll('.gridItem').length).toEqual(8); // 2 rows x 4 columns
    });
    it('should not render more columns than available if the area is not filled', function () {
      var rendered = findDOMNode(render(getMarkup({
        columnCount: 2
      })));
      expect(rendered.querySelectorAll('.gridItem').length).toEqual(10); // 5 rows x 2 columns
    }); // Small performance tweak added in 5.5.6

    it('should not render/parent cells that are null or false', function () {
      function cellRenderer(_ref3) {
        var columnIndex = _ref3.columnIndex,
            key = _ref3.key,
            rowIndex = _ref3.rowIndex,
            style = _ref3.style;

        if (columnIndex === 0) {
          return null;
        } else if (rowIndex === 0) {
          return false;
        } else {
          return React.createElement("div", {
            className: "cell",
            key: key,
            style: style
          }, "row:".concat(rowIndex, ", column:").concat(columnIndex));
        }
      }

      var rendered = findDOMNode(render(getMarkup({
        columnCount: 3,
        overscanColumnCount: 0,
        overscanRowCount: 0,
        rowCount: 3,
        cellRenderer: cellRenderer
      })));
      expect(rendered.querySelectorAll('.cell').length).toEqual(4); // [1,1], [1,2], [2,1], and [2,2]

      expect(rendered.textContent).not.toContain('column:0');
      expect(rendered.textContent).not.toContain('row:0');
    });
    it('should scroll to the last existing point when rows are removed', function () {
      var grid = render(getMarkup({
        rowCount: 15
      }));
      simulateScroll({
        grid: grid,
        scrollTop: 200
      });
      var updatedGrid = render(getMarkup({
        rowCount: 10
      }));
      expect(updatedGrid.state.scrollTop).toEqual(100);
    });
    it('should scroll to the last existing point when columns are removed', function () {
      var grid = render(getMarkup({
        columnCount: 12
      }));
      simulateScroll({
        grid: grid,
        scrollLeft: 400
      });
      var updatedGrid = render(getMarkup({
        columnCount: 8
      }));
      expect(updatedGrid.state.scrollLeft).toEqual(200);
    });
    it('should not scroll unseen rows are removed', function () {
      render(getMarkup({
        rowCount: 15
      }));
      var updatedGrid = render(getMarkup({
        rowCount: 10
      }));
      expect(updatedGrid.state.scrollTop).toEqual(0);
    });
    it('should not scroll when unseen columns are removed', function () {
      render(getMarkup({
        columnCount: 12
      }));
      var updatedGrid = render(getMarkup({
        columnCount: 8
      }));
      expect(updatedGrid.state.scrollLeft).toEqual(0);
    });
  });
  describe('shows and hides scrollbars based on rendered content', function () {
    it('should set overflowX:hidden if columns fit within the available width and y-axis has no scrollbar', function () {
      var rendered = findDOMNode(render(getMarkup({
        columnCount: 4,
        getScrollbarSize: getScrollbarSize20,
        rowCount: 5
      })));
      expect(rendered.style.overflowX).toEqual('hidden');
    });
    it('should set overflowX:hidden if columns and y-axis scrollbar fit within the available width', function () {
      var rendered = findDOMNode(render(getMarkup({
        columnCount: 4,
        getScrollbarSize: getScrollbarSize20,
        width: 200 + getScrollbarSize20()
      })));
      expect(rendered.style.overflowX).toEqual('hidden');
    });
    it('should leave overflowX:auto if columns require more than the available width', function () {
      var rendered = findDOMNode(render(getMarkup({
        columnCount: 4,
        getScrollbarSize: getScrollbarSize20,
        width: 200 - 1,
        rowCount: 5
      })));
      expect(rendered.style.overflowX).not.toEqual('hidden');
    });
    it('should leave overflowX:auto if columns and y-axis scrollbar require more than the available width', function () {
      var rendered = findDOMNode(render(getMarkup({
        columnCount: 4,
        getScrollbarSize: getScrollbarSize20,
        width: 200 + getScrollbarSize20() - 1
      })));
      expect(rendered.style.overflowX).not.toEqual('hidden');
    });
    it('should set overflowY:hidden if rows fit within the available width and xaxis has no scrollbar', function () {
      var rendered = findDOMNode(render(getMarkup({
        getScrollbarSize: getScrollbarSize20,
        rowCount: 5,
        columnCount: 4
      })));
      expect(rendered.style.overflowY).toEqual('hidden');
    });
    it('should set overflowY:hidden if rows and x-axis scrollbar fit within the available width', function () {
      var rendered = findDOMNode(render(getMarkup({
        getScrollbarSize: getScrollbarSize20,
        rowCount: 5,
        height: 100 + getScrollbarSize20()
      })));
      expect(rendered.style.overflowY).toEqual('hidden');
    });
    it('should leave overflowY:auto if rows require more than the available width', function () {
      var rendered = findDOMNode(render(getMarkup({
        getScrollbarSize: getScrollbarSize20,
        rowCount: 5,
        height: 100 - 1,
        columnCount: 4
      })));
      expect(rendered.style.overflowY).not.toEqual('hidden');
    });
    it('should leave overflowY:auto if rows and x-axis scrollbar require more than the available width', function () {
      var rendered = findDOMNode(render(getMarkup({
        getScrollbarSize: getScrollbarSize20,
        rowCount: 5,
        height: 100 + getScrollbarSize20() - 1
      })));
      expect(rendered.style.overflowY).not.toEqual('hidden');
    });
    it('should accept styles that overwrite calculated ones', function () {
      var rendered = findDOMNode(render(getMarkup({
        columnCount: 1,
        getScrollbarSize: getScrollbarSize20,
        height: 1,
        rowCount: 1,
        style: {
          overflowY: 'visible',
          overflowX: 'visible'
        },
        width: 1
      })));
      expect(rendered.style.overflowY).toEqual('visible');
      expect(rendered.style.overflowX).toEqual('visible');
    });
  });
  /** Tests scrolling via initial props */

  describe(':scrollToColumn and :scrollToRow', function () {
    it('should scroll to the left', function () {
      var grid = render(getMarkup({
        scrollToColumn: 0
      }));
      expect(grid.state.scrollLeft).toEqual(0);
    });
    it('should scroll over to the middle', function () {
      var grid = render(getMarkup({
        scrollToColumn: 24
      })); // 50 columns * 50 item width = 2,500 total item width
      // 4 columns can be visible at a time and :scrollLeft is initially 0,
      // So the minimum amount of scrolling leaves the 25th item at the right (just scrolled into view).

      expect(grid.state.scrollLeft).toEqual(1050);
    });
    it('should scroll to the far right', function () {
      var grid = render(getMarkup({
        scrollToColumn: 49
      })); // 50 columns * 50 item width = 2,500 total item width
      // Target offset for the last item then is 2,500 - 200

      expect(grid.state.scrollLeft).toEqual(2300);
    });
    it('should scroll to the top', function () {
      var grid = render(getMarkup({
        scrollToRow: 0
      }));
      expect(grid.state.scrollTop).toEqual(0);
    });
    it('should scroll down to the middle', function () {
      var grid = render(getMarkup({
        scrollToRow: 49
      })); // 100 rows * 20 item height = 2,000 total item height
      // 5 rows can be visible at a time and :scrollTop is initially 0,
      // So the minimum amount of scrolling leaves the 50th item at the bottom (just scrolled into view).

      expect(grid.state.scrollTop).toEqual(900);
    });
    it('should scroll to the bottom', function () {
      var grid = render(getMarkup({
        scrollToRow: 99
      })); // 100 rows * 20 item height = 2,000 total item height
      // Target offset for the last item then is 2,000 - 100

      expect(grid.state.scrollTop).toEqual(1900);
    });
    it('should scroll to a row and column just added', function () {
      var grid = render(getMarkup());
      expect(grid.state.scrollLeft).toEqual(0);
      expect(grid.state.scrollTop).toEqual(0);
      grid = render(getMarkup({
        columnCount: NUM_COLUMNS + 1,
        rowCount: NUM_ROWS + 1,
        scrollToColumn: NUM_COLUMNS,
        scrollToRow: NUM_ROWS
      }));
      expect(grid.state.scrollLeft).toEqual(2350);
      expect(grid.state.scrollTop).toEqual(1920);
    });
    it('should scroll back to a newly-added cell without a change in prop', function () {
      var grid = render(getMarkup({
        columnCount: NUM_COLUMNS,
        rowCount: NUM_ROWS,
        scrollToColumn: NUM_COLUMNS,
        scrollToRow: NUM_ROWS
      }));
      grid = render(getMarkup({
        columnCount: NUM_COLUMNS + 1,
        rowCount: NUM_ROWS + 1,
        scrollToColumn: NUM_COLUMNS,
        scrollToRow: NUM_ROWS
      }));
      expect(grid.state.scrollLeft).toEqual(2350);
      expect(grid.state.scrollTop).toEqual(1920);
    });
    it('should scroll to the correct position for :scrollToAlignment "start"', function () {
      var grid = render(getMarkup({
        scrollToAlignment: 'start',
        scrollToColumn: 24,
        scrollToRow: 49
      })); // 50 columns * 50 item width = 2,500 total item width
      // 100 rows * 20 item height = 2,000 total item height
      // 4 columns and 5 rows can be visible at a time.
      // The minimum amount of scrolling leaves the specified cell in the bottom/right corner (just scrolled into view).
      // Since alignment is set to "start" we should scroll past this point until the cell is aligned top/left.

      expect(grid.state.scrollLeft).toEqual(1200);
      expect(grid.state.scrollTop).toEqual(980);
    });
    it('should scroll to the correct position for :scrollToAlignment "end"', function () {
      render(getMarkup({
        scrollToColumn: 99,
        scrollToRow: 99
      }));
      var grid = render(getMarkup({
        scrollToAlignment: 'end',
        scrollToColumn: 24,
        scrollToRow: 49
      })); // 50 columns * 50 item width = 2,500 total item width
      // 100 rows * 20 item height = 2,000 total item height
      // We first scroll past the specified cell and then back.
      // The minimum amount of scrolling then should leave the specified cell in the top/left corner (just scrolled into view).
      // Since alignment is set to "end" we should scroll past this point until the cell is aligned bottom/right.

      expect(grid.state.scrollLeft).toEqual(1050);
      expect(grid.state.scrollTop).toEqual(900);
    });
    it('should scroll to the correct position for :scrollToAlignment "center"', function () {
      render(getMarkup({
        scrollToColumn: 99,
        scrollToRow: 99
      }));
      var grid = render(getMarkup({
        scrollToAlignment: 'center',
        scrollToColumn: 24,
        scrollToRow: 49
      })); // 50 columns * 50 item width = 2,500 total item width
      // Viewport width is 200
      // Column 24 starts at 1,200, center point at 1,225, so...

      expect(grid.state.scrollLeft).toEqual(1125); // 100 rows * 20 item height = 2,000 total item height
      // Viewport height is 100
      // Row 49 starts at 980, center point at 990, so...

      expect(grid.state.scrollTop).toEqual(940);
    }); // Tests issue #691

    it('should set the correct :scrollLeft after height increases from 0', function () {
      render.unmount();
      expect(findDOMNode(render(getMarkup({
        height: 0,
        scrollToColumn: 24
      }))).scrollLeft || 0).toEqual(0);
      expect(findDOMNode(render(getMarkup({
        height: 100,
        scrollToColumn: 24
      }))).scrollLeft).toEqual(1050);
    }); // Tests issue #691

    it('should set the correct :scrollTop after width increases from 0', function () {
      render.unmount();
      expect(findDOMNode(render(getMarkup({
        scrollToRow: 49,
        width: 0
      }))).scrollTop || 0).toEqual(0);
      expect(findDOMNode(render(getMarkup({
        scrollToRow: 49,
        width: 100
      }))).scrollTop).toEqual(900);
    }); // Tests issue #218

    it('should set the correct :scrollTop after row and column counts increase from 0', function () {
      var expectedScrollTop = 100 * DEFAULT_ROW_HEIGHT - DEFAULT_HEIGHT + DEFAULT_ROW_HEIGHT;
      render(getMarkup({
        columnCount: 0,
        rowCount: 150,
        scrollToRow: 100
      }));
      expect(findDOMNode(render(getMarkup({
        columnCount: 150,
        rowCount: 150,
        scrollToRow: 100
      }))).scrollTop).toEqual(expectedScrollTop);
    });
    it('should support scrollToCell() public method', function () {
      var grid = render(getMarkup());
      expect(grid.state.scrollLeft).toEqual(0);
      expect(grid.state.scrollTop).toEqual(0);
      grid.scrollToCell({
        columnIndex: 24,
        rowIndex: 49
      }); // 50 columns * 50 item width = 2,500 total item width
      // 4 columns can be visible at a time and :scrollLeft is initially 0,
      // So the minimum amount of scrolling leaves the 25th item at the right (just scrolled into view).

      expect(grid.state.scrollLeft).toEqual(1050); // 100 rows * 20 item height = 2,000 total item height
      // 5 rows can be visible at a time and :scrollTop is initially 0,
      // So the minimum amount of scrolling leaves the 50th item at the bottom (just scrolled into view).

      expect(grid.state.scrollTop).toEqual(900); // Change column without affecting row

      grid.scrollToCell({
        columnIndex: 49
      });
      expect(grid.state.scrollLeft).toEqual(2300);
      expect(grid.state.scrollTop).toEqual(900); // Change row without affecting column

      grid.scrollToCell({
        rowIndex: 99
      });
      expect(grid.state.scrollLeft).toEqual(2300);
      expect(grid.state.scrollTop).toEqual(1900);
    });
    it('should support scrollToPosition() public method', function () {
      var grid = render(getMarkup());
      expect(grid.state.scrollLeft).toEqual(0);
      expect(grid.state.scrollTop).toEqual(0);
      grid.scrollToPosition({
        scrollLeft: 50,
        scrollTop: 100
      });
      expect(grid.state.scrollLeft).toEqual(50);
      expect(grid.state.scrollTop).toEqual(100); // Change column without affecting row

      grid.scrollToPosition({
        scrollLeft: 25
      });
      expect(grid.state.scrollLeft).toEqual(25);
      expect(grid.state.scrollTop).toEqual(100); // Change row without affecting column

      grid.scrollToPosition({
        scrollTop: 50
      });
      expect(grid.state.scrollLeft).toEqual(25);
      expect(grid.state.scrollTop).toEqual(50);
    });
    it('should support handleScrollEvent() public method', function () {
      var grid = render(getMarkup());
      expect(grid.state.scrollLeft).toEqual(0);
      expect(grid.state.scrollTop).toEqual(0);
      grid.handleScrollEvent({
        scrollLeft: 50,
        scrollTop: 100
      });
      expect(grid.state.isScrolling).toEqual(true);
      expect(grid.state.scrollLeft).toEqual(50);
      expect(grid.state.scrollTop).toEqual(100);
    });
    it('should support getOffsetForCell() public method', function () {
      var grid = render(getMarkup());

      var _grid$getOffsetForCel = grid.getOffsetForCell({
        columnIndex: 24,
        rowIndex: 49
      }),
          scrollLeft = _grid$getOffsetForCel.scrollLeft,
          scrollTop = _grid$getOffsetForCel.scrollTop; // 50 columns * 50 item width = 2,500 total item width
      // 4 columns can be visible at a time and :scrollLeft is initially 0,
      // So the minimum amount of scrolling leaves the 25th item at the right (just scrolled into view).


      expect(scrollLeft).toEqual(1050); // 100 rows * 20 item height = 2,000 total item height
      // 5 rows can be visible at a time and :scrollTop is initially 0,
      // So the minimum amount of scrolling leaves the 50th item at the bottom (just scrolled into view).

      expect(scrollTop).toEqual(900);
    });
    it('should support getTotalRowsHeight() public method', function () {
      var grid = render(getMarkup());
      grid.recomputeGridSize();
      var totalHeight = grid.getTotalRowsHeight(); // 100 rows * 20 item height = 2,000 total item height

      expect(totalHeight).toEqual(2000);
    });
    it('should support getTotalColumnsWidth() public method', function () {
      var grid = render(getMarkup());
      grid.recomputeGridSize();
      var totalWidth = grid.getTotalColumnsWidth(); // 50 columns * 50 item width = 2,500 total item width

      expect(totalWidth).toEqual(2500);
    }); // See issue #565

    it('should update scroll position to account for changed cell sizes within a function prop wrapper', function () {
      var _rowHeight = 20;
      var props = {
        height: 100,
        rowCount: 100,
        rowHeight: function rowHeight(_ref4) {
          var index = _ref4.index;
          return index === 99 ? _rowHeight : 20;
        },
        scrollToRow: 99
      };
      var grid = render(getMarkup(props));
      var node = findDOMNode(grid);
      expect(node.scrollTop).toBe(1900);
      _rowHeight = 40;
      grid.recomputeGridSize({
        rowIndex: 99
      });
      expect(node.scrollTop).toBe(1920);
    });
    it('should not restore scrollLeft when scrolling left and recomputeGridSize with columnIndex smaller than scrollToColumn', function () {
      var props = {
        columnWidth: 50,
        columnCount: 100,
        height: 100,
        rowCount: 100,
        rowHeight: 20,
        scrollToColumn: 50,
        scrollToRow: 50,
        width: 100
      };
      var grid = render(getMarkup(props));
      expect(grid.state.scrollLeft).toEqual(2450);
      simulateScroll({
        grid: grid,
        scrollLeft: 2250
      });
      expect(grid.state.scrollLeft).toEqual(2250);
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_BACKWARD);
      grid.recomputeGridSize({
        columnIndex: 30
      });
      expect(grid.state.scrollLeft).toEqual(2250);
    });
    it('should not restore scrollTop when scrolling up and recomputeGridSize with rowIndex smaller than scrollToRow', function () {
      var props = {
        columnWidth: 50,
        columnCount: 100,
        height: 100,
        rowCount: 100,
        rowHeight: 20,
        scrollToColumn: 50,
        scrollToRow: 50,
        width: 100
      };
      var grid = render(getMarkup(props));
      expect(grid.state.scrollTop).toEqual(920);
      simulateScroll({
        grid: grid,
        scrollTop: 720
      });
      expect(grid.state.scrollTop).toEqual(720);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_BACKWARD);
      grid.recomputeGridSize({
        rowIndex: 20
      });
      expect(grid.state.scrollTop).toEqual(720);
    });
    it('should restore scroll offset for column when row count increases from 0 (and vice versa)', function () {
      var props = {
        columnWidth: 50,
        columnCount: 100,
        height: 100,
        rowCount: 100,
        rowHeight: 20,
        scrollToColumn: 50,
        scrollToRow: 50,
        width: 100
      };
      var grid = render(getMarkup(props));
      expect(grid.state.scrollLeft).toEqual(2450);
      expect(grid.state.scrollTop).toEqual(920);
      render(getMarkup(_objectSpread({}, props, {
        columnCount: 0
      })));
      expect(grid.state.scrollLeft).toEqual(0);
      expect(grid.state.scrollTop).toEqual(0);
      render(getMarkup(props));
      expect(grid.state.scrollLeft).toEqual(2450);
      expect(grid.state.scrollTop).toEqual(920);
      render(getMarkup(_objectSpread({}, props, {
        rowCount: 0
      })));
      expect(grid.state.scrollLeft).toEqual(0);
      expect(grid.state.scrollTop).toEqual(0);
      render(getMarkup(props));
      expect(grid.state.scrollLeft).toEqual(2450);
      expect(grid.state.scrollTop).toEqual(920);
    });
    it('should take scrollbar size into account when aligning cells', function () {
      var grid = render(getMarkup({
        columnWidth: 50,
        columnCount: 100,
        getScrollbarSize: getScrollbarSize20,
        height: 100,
        rowCount: 100,
        rowHeight: 20,
        scrollToColumn: 50,
        scrollToRow: 50,
        width: 100
      }));
      expect(grid.state.scrollLeft).toEqual(2450 + getScrollbarSize20());
      expect(grid.state.scrollTop).toEqual(920 + getScrollbarSize20());
    });
  });
  describe('property updates', function () {
    it('should update :scrollToColumn position when :columnWidth changes', function () {
      var grid = findDOMNode(render(getMarkup({
        scrollToColumn: 25
      })));
      expect(grid.textContent).toContain('column:25'); // Making columns taller pushes name off/beyond the scrolled area

      grid = findDOMNode(render(getMarkup({
        scrollToColumn: 25,
        columnWidth: 20
      })));
      expect(grid.textContent).toContain('column:25');
    });
    it('should update :scrollToRow position when :rowHeight changes', function () {
      var grid = findDOMNode(render(getMarkup({
        scrollToRow: 50
      })));
      expect(grid.textContent).toContain('row:50'); // Making rows taller pushes name off/beyond the scrolled area

      grid = findDOMNode(render(getMarkup({
        scrollToRow: 50,
        rowHeight: 20
      })));
      expect(grid.textContent).toContain('row:50');
    });
    it('should update :scrollToColumn position when :width changes', function () {
      var grid = findDOMNode(render(getMarkup({
        scrollToColumn: 25
      })));
      expect(grid.textContent).toContain('column:25'); // Making the grid narrower leaves only room for 1 item

      grid = findDOMNode(render(getMarkup({
        scrollToColumn: 25,
        width: 50
      })));
      expect(grid.textContent).toContain('column:25');
    });
    it('should update :scrollToRow position when :height changes', function () {
      var grid = findDOMNode(render(getMarkup({
        scrollToRow: 50
      })));
      expect(grid.textContent).toContain('row:50'); // Making the grid shorter leaves only room for 1 item

      grid = findDOMNode(render(getMarkup({
        scrollToRow: 50,
        height: 20
      })));
      expect(grid.textContent).toContain('row:50');
    });
    it('should update :scrollToColumn position when :scrollToColumn changes', function () {
      var grid = findDOMNode(render(getMarkup()));
      expect(grid.textContent).not.toContain('column:25');
      grid = findDOMNode(render(getMarkup({
        scrollToColumn: 25
      })));
      expect(grid.textContent).toContain('column:25');
    });
    it('should update :scrollToRow position when :scrollToRow changes', function () {
      var grid = findDOMNode(render(getMarkup()));
      expect(grid.textContent).not.toContain('row:50');
      grid = findDOMNode(render(getMarkup({
        scrollToRow: 50
      })));
      expect(grid.textContent).toContain('row:50');
    });
    it('should update scroll position if size shrinks smaller than the current scroll', function () {
      var grid = findDOMNode(render(getMarkup({
        scrollToColumn: 250
      })));
      grid = findDOMNode(render(getMarkup()));
      grid = findDOMNode(render(getMarkup({
        scrollToColumn: 250,
        columnCount: 10
      })));
      expect(grid.textContent).toContain('column:9');
    });
    it('should update scroll position if size shrinks smaller than the current scroll', function () {
      var grid = findDOMNode(render(getMarkup({
        scrollToRow: 500
      })));
      grid = findDOMNode(render(getMarkup()));
      grid = findDOMNode(render(getMarkup({
        scrollToRow: 500,
        rowCount: 10
      })));
      expect(grid.textContent).toContain('row:9');
    });
  });
  describe('noContentRenderer', function () {
    it('should call :noContentRenderer if :columnCount is 0', function () {
      var list = findDOMNode(render(getMarkup({
        noContentRenderer: function noContentRenderer() {
          return React.createElement("div", null, "No data");
        },
        columnCount: 0
      })));
      expect(list.textContent).toEqual('No data');
    });
    it('should call :noContentRenderer if :rowCount is 0', function () {
      var list = findDOMNode(render(getMarkup({
        noContentRenderer: function noContentRenderer() {
          return React.createElement("div", null, "No data");
        },
        rowCount: 0
      })));
      expect(list.textContent).toEqual('No data');
    }); // Sanity check for bvaughn/react-virtualized/pull/348

    it('should render an empty body if :rowCount or :columnCount changes to 0', function () {
      function noContentRenderer() {
        return React.createElement("div", null, "No data");
      }

      var list = findDOMNode(render(getMarkup({
        noContentRenderer: noContentRenderer
      })));
      expect(list.textContent).not.toEqual('No data');
      list = findDOMNode(render(getMarkup({
        noContentRenderer: noContentRenderer,
        rowCount: 0
      })));
      expect(list.textContent).toEqual('No data');
      list = findDOMNode(render(getMarkup({
        noContentRenderer: noContentRenderer
      })));
      expect(list.textContent).not.toEqual('No data');
      list = findDOMNode(render(getMarkup({
        columnCount: 0,
        noContentRenderer: noContentRenderer
      })));
      expect(list.textContent).toEqual('No data');
    });
    it('should render an empty body if :columnCount is 0 and there is no :noContentRenderer', function () {
      var list = findDOMNode(render(getMarkup({
        columnCount: 0
      })));
      expect(list.textContent).toEqual('');
    });
    it('should render an empty body if :rowCount is 0 and there is no :noContentRenderer', function () {
      var list = findDOMNode(render(getMarkup({
        rowCount: 0
      })));
      expect(list.textContent).toEqual('');
    });
    it('should render an empty body there is a :noContentRenderer but :height or :width are 0', function () {
      var list = findDOMNode(render(getMarkup({
        height: 0,
        noContentRenderer: function noContentRenderer() {
          return React.createElement("div", null, "No data");
        }
      })));
      expect(list.textContent).toEqual('');
      list = findDOMNode(render(getMarkup({
        noContentRenderer: function noContentRenderer() {
          return React.createElement("div", null, "No data");
        },
        width: 0
      })));
      expect(list.textContent).toEqual('');
    });
  });
  describe('onSectionRendered', function () {
    it('should call :onSectionRendered if at least one cell is rendered', function () {
      var columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex;
      render(getMarkup({
        onSectionRendered: function onSectionRendered(params) {
          var _params;

          return _params = params, columnStartIndex = _params.columnStartIndex, columnStopIndex = _params.columnStopIndex, rowStartIndex = _params.rowStartIndex, rowStopIndex = _params.rowStopIndex, _params;
        }
      }));
      expect(columnStartIndex).toEqual(0);
      expect(columnStopIndex).toEqual(3);
      expect(rowStartIndex).toEqual(0);
      expect(rowStopIndex).toEqual(4);
    });
    it('should not call :onSectionRendered unless the column or row start or stop indices have changed', function () {
      var numCalls = 0;
      var columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex;

      var onSectionRendered = function onSectionRendered(params) {
        columnStartIndex = params.columnStartIndex;
        columnStopIndex = params.columnStopIndex;
        rowStartIndex = params.rowStartIndex;
        rowStopIndex = params.rowStopIndex;
        numCalls++;
      };

      render(getMarkup({
        onSectionRendered: onSectionRendered
      }));
      expect(numCalls).toEqual(1);
      expect(columnStartIndex).toEqual(0);
      expect(columnStopIndex).toEqual(3);
      expect(rowStartIndex).toEqual(0);
      expect(rowStopIndex).toEqual(4);
      render(getMarkup({
        onSectionRendered: onSectionRendered
      }));
      expect(numCalls).toEqual(1);
      expect(columnStartIndex).toEqual(0);
      expect(columnStopIndex).toEqual(3);
      expect(rowStartIndex).toEqual(0);
      expect(rowStopIndex).toEqual(4);
    });
    it('should call :onSectionRendered if the row or column start or stop indices have changed', function () {
      var numCalls = 0;
      var columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex;

      var onSectionRendered = function onSectionRendered(params) {
        columnStartIndex = params.columnStartIndex;
        columnStopIndex = params.columnStopIndex;
        rowStartIndex = params.rowStartIndex;
        rowStopIndex = params.rowStopIndex;
        numCalls++;
      };

      render(getMarkup({
        onSectionRendered: onSectionRendered
      }));
      expect(columnStartIndex).toEqual(0);
      expect(columnStopIndex).toEqual(3);
      expect(rowStartIndex).toEqual(0);
      expect(rowStopIndex).toEqual(4);
      render(getMarkup({
        height: 50,
        onSectionRendered: onSectionRendered
      }));
      expect(numCalls).toEqual(2);
      expect(columnStartIndex).toEqual(0);
      expect(columnStopIndex).toEqual(3);
      expect(rowStartIndex).toEqual(0);
      expect(rowStopIndex).toEqual(2);
      render(getMarkup({
        height: 50,
        onSectionRendered: onSectionRendered,
        width: 100
      }));
      expect(numCalls).toEqual(3);
      expect(columnStartIndex).toEqual(0);
      expect(columnStopIndex).toEqual(1);
      expect(rowStartIndex).toEqual(0);
      expect(rowStopIndex).toEqual(2);
    });
    it('should not call :onSectionRendered if no cells are rendered', function () {
      var numCalls = 0;
      render(getMarkup({
        height: 0,
        onSectionRendered: function onSectionRendered() {
          return numCalls++;
        }
      }));
      expect(numCalls).toEqual(0);
    });
  });
  describe(':scrollLeft and :scrollTop properties', function () {
    it('should render correctly when an initial :scrollLeft and :scrollTop properties are specified', function () {
      var columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex;
      findDOMNode(render(getMarkup({
        onSectionRendered: function onSectionRendered(params) {
          var _params2;

          return _params2 = params, columnStartIndex = _params2.columnStartIndex, columnStopIndex = _params2.columnStopIndex, rowStartIndex = _params2.rowStartIndex, rowStopIndex = _params2.rowStopIndex, _params2;
        },
        scrollLeft: 250,
        scrollTop: 100
      })));
      expect(rowStartIndex).toEqual(5);
      expect(rowStopIndex).toEqual(9);
      expect(columnStartIndex).toEqual(5);
      expect(columnStopIndex).toEqual(8);
    });
    it('should render correctly when :scrollLeft and :scrollTop properties are updated', function () {
      var columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex;
      render(getMarkup({
        onSectionRendered: function onSectionRendered(params) {
          var _params3;

          return _params3 = params, columnStartIndex = _params3.columnStartIndex, columnStopIndex = _params3.columnStopIndex, rowStartIndex = _params3.rowStartIndex, rowStopIndex = _params3.rowStopIndex, _params3;
        }
      }));
      expect(rowStartIndex).toEqual(0);
      expect(rowStopIndex).toEqual(4);
      expect(columnStartIndex).toEqual(0);
      expect(columnStopIndex).toEqual(3);
      render(getMarkup({
        onSectionRendered: function onSectionRendered(params) {
          var _params4;

          return _params4 = params, columnStartIndex = _params4.columnStartIndex, columnStopIndex = _params4.columnStopIndex, rowStartIndex = _params4.rowStartIndex, rowStopIndex = _params4.rowStopIndex, _params4;
        },
        scrollLeft: 250,
        scrollTop: 100
      }));
      expect(rowStartIndex).toEqual(5);
      expect(rowStopIndex).toEqual(9);
      expect(columnStartIndex).toEqual(5);
      expect(columnStopIndex).toEqual(8);
    });
  });
  describe('styles, classNames, and ids', function () {
    it('should use the expected global CSS classNames', function () {
      var rendered = findDOMNode(render(getMarkup()));
      expect(rendered.className).toEqual('ReactVirtualized__Grid');
    });
    it('should use a custom :className if specified', function () {
      var rendered = findDOMNode(render(getMarkup({
        className: 'foo'
      })));
      expect(rendered.className).toContain('foo');
    });
    it('should use a custom :id if specified', function () {
      var rendered = findDOMNode(render(getMarkup({
        id: 'bar'
      })));
      expect(rendered.getAttribute('id')).toEqual('bar');
    });
    it('should use a custom :style if specified', function () {
      var style = {
        backgroundColor: 'red'
      };
      var rendered = findDOMNode(render(getMarkup({
        style: style
      })));
      expect(rendered.style.backgroundColor).toEqual('red');
    });
    it('should use a custom :containerStyle if specified', function () {
      var containerStyle = {
        backgroundColor: 'red'
      };
      var rendered = findDOMNode(render(getMarkup({
        containerStyle: containerStyle
      })));
      expect(rendered.querySelector('.ReactVirtualized__Grid__innerScrollContainer').style.backgroundColor).toEqual('red');
    });
  });
  describe('onScroll', function () {
    it('should trigger callback when component is mounted', function () {
      var onScrollCalls = [];
      render(getMarkup({
        onScroll: function onScroll(params) {
          return onScrollCalls.push(params);
        },
        scrollLeft: 50,
        scrollTop: 100
      }));
      expect(onScrollCalls).toEqual([{
        clientHeight: 100,
        clientWidth: 200,
        scrollHeight: 2000,
        scrollLeft: 50,
        scrollTop: 100,
        scrollWidth: 2500
      }]);
    });
    it('should trigger callback when component scrolls horizontally', function () {
      var onScrollCalls = [];
      var grid = render(getMarkup({
        onScroll: function onScroll(params) {
          return onScrollCalls.push(params);
        }
      }));
      simulateScroll({
        grid: grid,
        scrollLeft: 100,
        scrollTop: 0
      });
      expect(onScrollCalls.length).toEqual(2);
      expect(onScrollCalls[1]).toEqual({
        clientHeight: 100,
        clientWidth: 200,
        scrollHeight: 2000,
        scrollLeft: 100,
        scrollTop: 0,
        scrollWidth: 2500
      });
    });
    it('should trigger callback when component scrolls vertically', function () {
      var onScrollCalls = [];
      var grid = render(getMarkup({
        onScroll: function onScroll(params) {
          return onScrollCalls.push(params);
        }
      }));
      simulateScroll({
        grid: grid,
        scrollLeft: 0,
        scrollTop: 100
      });
      expect(onScrollCalls.length).toEqual(2);
      expect(onScrollCalls[1]).toEqual({
        clientHeight: 100,
        clientWidth: 200,
        scrollHeight: 2000,
        scrollLeft: 0,
        scrollTop: 100,
        scrollWidth: 2500
      });
    });
    it('should trigger callback with scrollLeft of 0 when total columns width is less than width', function () {
      var onScrollCalls = [];
      var grid = render(getMarkup({
        columnCount: 1,
        columnWidth: 50,
        onScroll: function onScroll(params) {
          return onScrollCalls.push(params);
        },
        scrollLeft: 0,
        scrollTop: 10,
        width: 200
      }));
      simulateScroll({
        grid: grid,
        scrollLeft: 0,
        scrollTop: 0
      });
      expect(onScrollCalls.length).toEqual(2);
      expect(onScrollCalls[1]).toEqual({
        clientHeight: 100,
        clientWidth: 200,
        scrollHeight: 2000,
        scrollLeft: 0,
        scrollTop: 0,
        scrollWidth: 50
      });
    });
    it('should trigger callback with scrollTop of 0 when total rows height is less than height', function () {
      var onScrollCalls = [];
      var grid = render(getMarkup({
        rowCount: 1,
        rowHeight: 50,
        onScroll: function onScroll(params) {
          return onScrollCalls.push(params);
        },
        scrollLeft: 0,
        scrollTop: 10,
        height: 200
      }));
      simulateScroll({
        grid: grid,
        scrollLeft: 0,
        scrollTop: 0
      });
      expect(onScrollCalls.length).toEqual(2);
      expect(onScrollCalls[1]).toEqual({
        clientHeight: 200,
        clientWidth: 200,
        scrollHeight: 50,
        scrollLeft: 0,
        scrollTop: 0,
        scrollWidth: 2500
      });
    }); // Support use-cases like WindowScroller; enable them to stay in sync with scroll-to-cell changes.

    it('should trigger when :scrollToColumn or :scrollToRow are changed via props', function () {
      var onScrollCalls = [];
      render(getMarkup());
      render(getMarkup({
        onScroll: function onScroll(params) {
          return onScrollCalls.push(params);
        },
        scrollToColumn: 24,
        scrollToRow: 49
      }));
      expect(onScrollCalls).toEqual([{
        clientHeight: 100,
        clientWidth: 200,
        scrollHeight: 2000,
        scrollLeft: 1050,
        scrollTop: 900,
        scrollWidth: 2500
      }]);
    });
  });
  describe('overscanColumnCount & overscanRowCount', function () {
    function createHelper() {
      var _columnOverscanStartIndex, _columnOverscanStopIndex, _columnStartIndex, _columnStopIndex, _rowOverscanStartIndex, _rowOverscanStopIndex, _rowStartIndex, _rowStopIndex;

      function onSectionRendered(params) {
        _columnOverscanStartIndex = params.columnOverscanStartIndex;
        _columnOverscanStopIndex = params.columnOverscanStopIndex;
        _columnStartIndex = params.columnStartIndex;
        _columnStopIndex = params.columnStopIndex;
        _rowOverscanStartIndex = params.rowOverscanStartIndex;
        _rowOverscanStopIndex = params.rowOverscanStopIndex;
        _rowStartIndex = params.rowStartIndex;
        _rowStopIndex = params.rowStopIndex;
      }

      return {
        columnOverscanStartIndex: function columnOverscanStartIndex() {
          return _columnOverscanStartIndex;
        },
        columnOverscanStopIndex: function columnOverscanStopIndex() {
          return _columnOverscanStopIndex;
        },
        columnStartIndex: function columnStartIndex() {
          return _columnStartIndex;
        },
        columnStopIndex: function columnStopIndex() {
          return _columnStopIndex;
        },
        onSectionRendered: onSectionRendered,
        rowOverscanStartIndex: function rowOverscanStartIndex() {
          return _rowOverscanStartIndex;
        },
        rowOverscanStopIndex: function rowOverscanStopIndex() {
          return _rowOverscanStopIndex;
        },
        rowStartIndex: function rowStartIndex() {
          return _rowStartIndex;
        },
        rowStopIndex: function rowStopIndex() {
          return _rowStopIndex;
        }
      };
    }

    it('should not overscan if disabled', function () {
      var helper = createHelper();
      render(getMarkup({
        onSectionRendered: helper.onSectionRendered
      }));
      expect(helper.columnOverscanStartIndex()).toEqual(helper.columnStartIndex());
      expect(helper.columnOverscanStopIndex()).toEqual(helper.columnStopIndex());
      expect(helper.rowOverscanStartIndex()).toEqual(helper.rowStartIndex());
      expect(helper.rowOverscanStopIndex()).toEqual(helper.rowStopIndex());
    });
    it('should overscan the specified amount', function () {
      var helper = createHelper();
      render(getMarkup({
        onSectionRendered: helper.onSectionRendered,
        overscanColumnCount: 2,
        overscanRowCount: 5,
        scrollToColumn: 25,
        scrollToRow: 50
      }));
      expect(helper.columnOverscanStartIndex()).toEqual(22);
      expect(helper.columnOverscanStopIndex()).toEqual(27);
      expect(helper.columnStartIndex()).toEqual(22);
      expect(helper.columnStopIndex()).toEqual(25);
      expect(helper.rowOverscanStartIndex()).toEqual(46);
      expect(helper.rowOverscanStopIndex()).toEqual(55);
      expect(helper.rowStartIndex()).toEqual(46);
      expect(helper.rowStopIndex()).toEqual(50);
    });
    it('should not overscan beyond the bounds of the grid', function () {
      var helper = createHelper();
      render(getMarkup({
        onSectionRendered: helper.onSectionRendered,
        columnCount: 6,
        overscanColumnCount: 10,
        overscanRowCount: 10,
        rowCount: 5
      }));
      expect(helper.columnOverscanStartIndex()).toEqual(0);
      expect(helper.columnOverscanStopIndex()).toEqual(5);
      expect(helper.columnStartIndex()).toEqual(0);
      expect(helper.columnStopIndex()).toEqual(3);
      expect(helper.rowOverscanStartIndex()).toEqual(0);
      expect(helper.rowOverscanStopIndex()).toEqual(4);
      expect(helper.rowStartIndex()).toEqual(0);
      expect(helper.rowStopIndex()).toEqual(4);
    });
    it('should set the correct scroll direction', function () {
      // Do not pass in the initial state as props, otherwise the internal state is forbidden from updating itself
      var grid = render(getMarkup()); // Simulate a scroll to set the initial internal state

      simulateScroll({
        grid: grid,
        scrollLeft: 50,
        scrollTop: 50
      });
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_FORWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_FORWARD);
      simulateScroll({
        grid: grid,
        scrollLeft: 0,
        scrollTop: 0
      });
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_BACKWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_BACKWARD);
      simulateScroll({
        grid: grid,
        scrollLeft: 100,
        scrollTop: 100
      });
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_FORWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_FORWARD);
    });
    it('should set the correct scroll direction when scroll position is updated from props', function () {
      var grid = render(getMarkup({
        scrollLeft: 50,
        scrollTop: 50
      }));
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_FORWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_FORWARD);
      grid = render(getMarkup({
        scrollLeft: 0,
        scrollTop: 0
      }));
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_BACKWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_BACKWARD);
      grid = render(getMarkup({
        scrollLeft: 100,
        scrollTop: 100
      }));
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_FORWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_FORWARD);
    });
    it('should not reset scroll direction for one axis when scrolled in another', function () {
      // Do not pass in the initial state as props, otherwise the internal state is forbidden from updating itself
      var grid = render(getMarkup()); // Simulate a scroll to set the initial internal state

      simulateScroll({
        grid: grid,
        scrollLeft: 0,
        scrollTop: 5
      });
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_FORWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_FORWARD);
      simulateScroll({
        grid: grid,
        scrollLeft: 5,
        scrollTop: 5
      });
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_FORWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_FORWARD);
      simulateScroll({
        grid: grid,
        scrollLeft: 5,
        scrollTop: 0
      });
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_FORWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_BACKWARD);
      simulateScroll({
        grid: grid,
        scrollLeft: 0,
        scrollTop: 0
      });
      expect(grid.state.scrollDirectionHorizontal).toEqual(SCROLL_DIRECTION_BACKWARD);
      expect(grid.state.scrollDirectionVertical).toEqual(SCROLL_DIRECTION_BACKWARD);
    });
    it('should overscan in the direction being scrolled', function _callee(done) {
      var helper, onSectionRenderedResolve, onSectionRendered, grid, onSectionRenderedPromise;
      return _regeneratorRuntime.async(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              onSectionRendered = function _ref5(params) {
                helper.onSectionRendered(params);

                if (onSectionRenderedResolve) {
                  onSectionRenderedResolve();
                }
              };

              helper = createHelper();
              grid = render(getMarkup({
                onSectionRendered: onSectionRendered,
                overscanColumnCount: 2,
                overscanRowCount: 5
              })); // Wait until the onSectionRendered handler / debouncer has processed

              onSectionRenderedPromise = new Promise(function (resolve) {
                onSectionRenderedResolve = resolve;
              });
              simulateScroll({
                grid: grid,
                scrollLeft: 200,
                scrollTop: 200
              });
              _context.next = 7;
              return _regeneratorRuntime.awrap(onSectionRenderedPromise);

            case 7:
              // It should overscan in the direction being scrolled while scroll is in progress
              expect(helper.columnOverscanStartIndex()).toEqual(4);
              expect(helper.columnOverscanStopIndex()).toEqual(9);
              expect(helper.columnStartIndex()).toEqual(4);
              expect(helper.columnStopIndex()).toEqual(7);
              expect(helper.rowOverscanStartIndex()).toEqual(10);
              expect(helper.rowOverscanStopIndex()).toEqual(19);
              expect(helper.rowStartIndex()).toEqual(10);
              expect(helper.rowStopIndex()).toEqual(14); // Wait until the onSectionRendered handler / debouncer has processed

              onSectionRenderedPromise = new Promise(function (resolve) {
                onSectionRenderedResolve = resolve;
              });
              simulateScroll({
                grid: grid,
                scrollLeft: 100,
                scrollTop: 100
              });
              _context.next = 19;
              return _regeneratorRuntime.awrap(onSectionRenderedPromise);

            case 19:
              // It reset overscan once scrolling has finished
              expect(helper.columnOverscanStartIndex()).toEqual(0);
              expect(helper.columnOverscanStopIndex()).toEqual(5);
              expect(helper.columnStartIndex()).toEqual(2);
              expect(helper.columnStopIndex()).toEqual(5);
              expect(helper.rowOverscanStartIndex()).toEqual(0);
              expect(helper.rowOverscanStopIndex()).toEqual(9);
              expect(helper.rowStartIndex()).toEqual(5);
              expect(helper.rowStopIndex()).toEqual(9);
              done();

            case 28:
            case "end":
              return _context.stop();
          }
        }
      });
    });
  });
  describe('cellRangeRenderer', function () {
    it('should use a custom :cellRangeRenderer if specified', function () {
      var cellRangeRendererCalled = 0;
      var cellRangeRendererParams;
      var rendered = findDOMNode(render(getMarkup({
        cellRangeRenderer: function cellRangeRenderer(params) {
          cellRangeRendererParams = params;
          cellRangeRendererCalled++;
          return [React.createElement("div", {
            key: "0"
          }, "Fake content")];
        }
      })));
      expect(cellRangeRendererCalled).toEqual(1);
      expect(cellRangeRendererParams.columnStartIndex).toEqual(0);
      expect(cellRangeRendererParams.columnStopIndex).toEqual(3);
      expect(cellRangeRendererParams.rowStartIndex).toEqual(0);
      expect(cellRangeRendererParams.rowStopIndex).toEqual(4);
      expect(rendered.textContent).toContain('Fake content');
    });
  });
  describe('estimated row and column sizes', function () {
    it('should not estimate sizes if actual sizes are numbers', function () {
      var grid = render(getMarkup({
        columnWidth: 100,
        estimatedColumnSize: 150,
        estimatedRowSize: 15,
        rowHeight: 20
      }));
      expect(Grid._getEstimatedColumnSize(grid.props)).toEqual(100);
      expect(Grid._getEstimatedRowSize(grid.props)).toEqual(20);
    });
    it('should estimate row and column sizes if actual sizes are functions', function () {
      var grid = render(getMarkup({
        columnWidth: function columnWidth() {
          return 100;
        },
        estimatedColumnSize: 150,
        estimatedRowSize: 15,
        rowHeight: function rowHeight() {
          return 20;
        }
      }));
      expect(Grid._getEstimatedColumnSize(grid.props)).toEqual(150);
      expect(Grid._getEstimatedRowSize(grid.props)).toEqual(15);
    });
  });
  it('should pass the cellRenderer an :isScrolling flag when scrolling is in progress', function _callee2(done) {
    var cellRendererCalls, cellRenderer, grid;
    return _regeneratorRuntime.async(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            cellRenderer = function _ref7(_ref6) {
              var columnIndex = _ref6.columnIndex,
                  isScrolling = _ref6.isScrolling,
                  key = _ref6.key,
                  rowIndex = _ref6.rowIndex,
                  style = _ref6.style;
              cellRendererCalls.push(isScrolling);
              return defaultCellRenderer({
                columnIndex: columnIndex,
                key: key,
                rowIndex: rowIndex,
                style: style
              });
            };

            cellRendererCalls = [];
            grid = render(getMarkup({
              cellRenderer: cellRenderer
            }));
            expect(cellRendererCalls[0]).toEqual(false);
            cellRendererCalls.splice(0); // Give React time to process the queued setState()

            _context2.next = 7;
            return _regeneratorRuntime.awrap(new Promise(function (resolve) {
              return setTimeout(resolve, 1);
            }));

          case 7:
            simulateScroll({
              grid: grid,
              scrollTop: 100
            });
            expect(cellRendererCalls[0]).toEqual(true);
            done();

          case 10:
          case "end":
            return _context2.stop();
        }
      }
    });
  });
  it('should pass the cellRenderer an :isScrolling flag based on props override', function () {
    var cellRenderer = jest.fn();
    cellRenderer.mockImplementation(function (_ref8) {
      var key = _ref8.key,
          style = _ref8.style;
      return React.createElement("div", {
        key: key,
        style: style
      });
    });
    render(getMarkup({
      cellRenderer: cellRenderer,
      isScrolling: true
    }));
    expect(cellRenderer).toHaveBeenCalled();
    expect(cellRenderer.mock.calls[0][0].isScrolling).toBe(true);
    cellRenderer.mockReset();
    render(getMarkup({
      cellRenderer: cellRenderer,
      isScrolling: false,
      width: DEFAULT_WIDTH + 1
    }));
    expect(cellRenderer).toHaveBeenCalled();
    expect(cellRenderer.mock.calls[0][0].isScrolling).toBe(false);
  });
  it('should pass the cellRenderer an :isVisible flag', function () {
    var cellRendererCalls = [];

    function cellRenderer(props) {
      cellRendererCalls.push(props);
      return defaultCellRenderer(props);
    }

    render(getMarkup({
      cellRenderer: cellRenderer,
      height: DEFAULT_ROW_HEIGHT,
      overscanColumnCount: 1,
      overscanRowCount: 1,
      width: DEFAULT_COLUMN_WIDTH
    }));
    cellRendererCalls.forEach(function (props) {
      expect(props.isVisible).toEqual(props.columnIndex === 0 && props.rowIndex === 0); // Only the first cell is visible
    });
  });
  describe('cell caching', function () {
    it('should not cache cells if the Grid is not scrolling', function () {
      var cellRendererCalls = [];

      function cellRenderer(_ref9) {
        var columnIndex = _ref9.columnIndex,
            key = _ref9.key,
            rowIndex = _ref9.rowIndex,
            style = _ref9.style;
        cellRendererCalls.push({
          columnIndex: columnIndex,
          rowIndex: rowIndex
        });
        return defaultCellRenderer({
          columnIndex: columnIndex,
          key: key,
          rowIndex: rowIndex,
          style: style
        });
      }

      var props = {
        cellRenderer: cellRenderer,
        columnWidth: 100,
        height: 40,
        rowHeight: 20,
        scrollToRow: 0,
        width: 100
      };
      render(getMarkup(_objectSpread({}, props, {
        scrollToRow: 0
      })));
      expect(cellRendererCalls).toEqual([{
        columnIndex: 0,
        rowIndex: 0
      }, {
        columnIndex: 0,
        rowIndex: 1
      }]);
      cellRendererCalls.splice(0);
      render(getMarkup(_objectSpread({}, props, {
        scrollToRow: 1
      })));
      expect(cellRendererCalls).toEqual([{
        columnIndex: 0,
        rowIndex: 0
      }, {
        columnIndex: 0,
        rowIndex: 1
      }]);
    });
    it('should not cache cells if the offsets are not adjusted', function () {
      var cellRendererCalls = [];

      function cellRenderer(_ref10) {
        var columnIndex = _ref10.columnIndex,
            key = _ref10.key,
            rowIndex = _ref10.rowIndex,
            style = _ref10.style;
        cellRendererCalls.push({
          columnIndex: columnIndex,
          rowIndex: rowIndex
        });
        return defaultCellRenderer({
          columnIndex: columnIndex,
          key: key,
          rowIndex: rowIndex,
          style: style
        });
      }

      var props = {
        cellRenderer: cellRenderer,
        columnWidth: 100,
        height: 40,
        rowHeight: 20,
        rowCount: 100000,
        scrollToRow: 0,
        width: 100
      };
      render(getMarkup(_objectSpread({}, props, {
        scrollToRow: 0
      })));
      expect(cellRendererCalls).toEqual([{
        columnIndex: 0,
        rowIndex: 0
      }, {
        columnIndex: 0,
        rowIndex: 1
      }]);
      cellRendererCalls.splice(0);
      render(getMarkup(_objectSpread({}, props, {
        scrollToRow: 1
      })));
      expect(cellRendererCalls).toEqual([{
        columnIndex: 0,
        rowIndex: 0
      }, {
        columnIndex: 0,
        rowIndex: 1
      }]);
    });
    it('should cache a cell once it has been rendered while scrolling', function () {
      var cellRendererCalls = [];

      function cellRenderer(_ref11) {
        var columnIndex = _ref11.columnIndex,
            key = _ref11.key,
            rowIndex = _ref11.rowIndex,
            style = _ref11.style;
        cellRendererCalls.push({
          columnIndex: columnIndex,
          rowIndex: rowIndex
        });
        return defaultCellRenderer({
          columnIndex: columnIndex,
          key: key,
          rowIndex: rowIndex,
          style: style
        });
      }

      var props = {
        cellRenderer: cellRenderer,
        columnWidth: 100,
        height: 40,
        rowHeight: 20,
        width: 100
      };
      var grid = render(getMarkup(_objectSpread({}, props, {
        scrollToRow: 0
      })));
      expect(cellRendererCalls).toEqual([{
        columnIndex: 0,
        rowIndex: 0
      }, {
        columnIndex: 0,
        rowIndex: 1
      }]);
      simulateScroll({
        grid: grid,
        scrollTop: 1
      });
      cellRendererCalls.splice(0); // Rows 0-2 have already rendered but row 3 is not yet visible
      // This means that only row 3 should be newly-created
      // The others should come from the cache

      render(getMarkup(_objectSpread({}, props, {
        scrollToRow: 3
      })));
      expect(cellRendererCalls).toEqual([{
        columnIndex: 0,
        rowIndex: 3
      }]);
    });
    it('should clear cache once :isScrolling is false', function _callee3(done) {
      var cellRendererCalls, cellRenderer, props, grid;
      return _regeneratorRuntime.async(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              cellRenderer = function _ref13(_ref12) {
                var columnIndex = _ref12.columnIndex,
                    key = _ref12.key,
                    rowIndex = _ref12.rowIndex,
                    style = _ref12.style;
                cellRendererCalls.push({
                  columnIndex: columnIndex,
                  rowIndex: rowIndex
                });
                return defaultCellRenderer({
                  columnIndex: columnIndex,
                  key: key,
                  rowIndex: rowIndex,
                  style: style
                });
              };

              cellRendererCalls = [];
              props = {
                cellRenderer: cellRenderer,
                columnWidth: 100,
                height: 40,
                rowHeight: 20,
                scrollToRow: 0,
                width: 100
              };
              grid = render(getMarkup(props));
              expect(cellRendererCalls).toEqual([{
                columnIndex: 0,
                rowIndex: 0
              }, {
                columnIndex: 0,
                rowIndex: 1
              }]);
              simulateScroll({
                grid: grid,
                scrollTop: 1
              }); // Allow scrolling timeout to complete so that cell cache is reset

              _context3.next = 8;
              return _regeneratorRuntime.awrap(new Promise(function (resolve) {
                return setTimeout(resolve, DEFAULT_SCROLLING_RESET_TIME_INTERVAL * 2);
              }));

            case 8:
              cellRendererCalls.splice(0);
              render(getMarkup(_objectSpread({}, props, {
                scrollToRow: 1
              })));
              expect(cellRendererCalls.length).not.toEqual(0);
              done();

            case 12:
            case "end":
              return _context3.stop();
          }
        }
      });
    });
    it('should clear cache once :isScrolling via props is false', function _callee4() {
      var cellRenderer, props, scrollingStyle;
      return _regeneratorRuntime.async(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              cellRenderer = jest.fn();
              cellRenderer.mockImplementation(function (params) {
                return React.createElement("div", {
                  key: params.key,
                  style: params.style
                });
              });
              props = {
                autoHeight: true,
                cellRenderer: cellRenderer,
                columnCount: 1,
                isScrolling: true,
                rowCount: 1
              };
              render(getMarkup(props));
              render(getMarkup(props));
              expect(cellRenderer).toHaveBeenCalledTimes(1); // Due to cell cache

              scrollingStyle = cellRenderer.mock.calls[0][0].style;
              cellRenderer.mockReset();
              render(getMarkup(_objectSpread({}, props, {
                isScrolling: false
              })));
              expect(cellRenderer.mock.calls[0][0].style).toBe(scrollingStyle);
              expect(cellRenderer).toHaveBeenCalledTimes(1); // Reset cache

              cellRenderer.mockReset();
              render(getMarkup(_objectSpread({}, props, {
                isScrolling: true
              })));
              expect(cellRenderer.mock.calls[0][0].style).not.toBe(scrollingStyle);
              expect(cellRenderer).toHaveBeenCalledTimes(1); // Only cached when scrolling

            case 15:
            case "end":
              return _context4.stop();
          }
        }
      });
    });
    it('should clear cache if :recomputeGridSize is called', function () {
      var cellRendererCalls = [];

      function cellRenderer(_ref14) {
        var columnIndex = _ref14.columnIndex,
            key = _ref14.key,
            rowIndex = _ref14.rowIndex,
            style = _ref14.style;
        cellRendererCalls.push({
          columnIndex: columnIndex,
          rowIndex: rowIndex
        });
        return defaultCellRenderer({
          columnIndex: columnIndex,
          key: key,
          rowIndex: rowIndex,
          style: style
        });
      }

      var props = {
        cellRenderer: cellRenderer,
        columnWidth: 100,
        height: 40,
        rowHeight: 20,
        scrollTop: 0,
        width: 100
      };
      var grid = render(getMarkup(props));
      expect(cellRendererCalls).toEqual([{
        columnIndex: 0,
        rowIndex: 0
      }, {
        columnIndex: 0,
        rowIndex: 1
      }]);
      simulateScroll({
        grid: grid,
        scrollTop: 1
      });
      cellRendererCalls.splice(0);
      grid.recomputeGridSize();
      expect(cellRendererCalls.length).not.toEqual(0);
    });
    it('should not clear cache if :isScrollingOptOut is true', function () {
      var cellRendererCalls = [];

      function cellRenderer(_ref15) {
        var columnIndex = _ref15.columnIndex,
            key = _ref15.key,
            rowIndex = _ref15.rowIndex,
            style = _ref15.style;
        cellRendererCalls.push({
          columnIndex: columnIndex,
          rowIndex: rowIndex
        });
        return defaultCellRenderer({
          columnIndex: columnIndex,
          key: key,
          rowIndex: rowIndex,
          style: style
        });
      }

      var props = {
        cellRenderer: cellRenderer,
        columnWidth: 100,
        height: 40,
        rowHeight: 20,
        scrollTop: 0,
        width: 100,
        isScrollingOptOut: true
      };
      render(getMarkup(props));
      render(getMarkup(props));
      expect(cellRendererCalls).toEqual([{
        columnIndex: 0,
        rowIndex: 0
      }, {
        columnIndex: 0,
        rowIndex: 1
      }]);
      cellRendererCalls.splice(0);
      render(getMarkup(_objectSpread({}, props, {
        isScrolling: false
      }))); // Visible cells are cached

      expect(cellRendererCalls.length).toEqual(0);
      render(getMarkup(_objectSpread({}, props, {
        isScrolling: true
      }))); // Only cleared non-visible cells

      expect(cellRendererCalls.length).toEqual(0);
    });
    it('should not trigger render by _debounceScrollEndedCallback if process slow table', function _callee5() {
      var scrollingResetTimeInterval, cellRangeRendererCalls, cellRangeRenderer, props, grid, i;
      return _regeneratorRuntime.async(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              cellRangeRenderer = function _ref16(props) {
                var startTime = Date.now();

                while (Date.now() - startTime <= scrollingResetTimeInterval) {
                  ;
                } // imitate very slow render


                cellRangeRendererCalls++;
                return defaultCellRangeRenderer(props);
              };

              scrollingResetTimeInterval = 50;
              cellRangeRendererCalls = 0;
              props = {
                scrollingResetTimeInterval: scrollingResetTimeInterval,
                cellRangeRenderer: cellRangeRenderer
              };
              grid = render(getMarkup(props));
              render(getMarkup(props));
              expect(cellRangeRendererCalls).toEqual(1);
              i = 1;

            case 8:
              if (!(i <= 5)) {
                _context5.next = 17;
                break;
              }

              cellRangeRendererCalls = 0;
              simulateScroll({
                grid: grid,
                scrollTop: i
              }); // small wait for maybe early _debounceScrollEndedCallback

              _context5.next = 13;
              return _regeneratorRuntime.awrap(new Promise(function (resolve) {
                return setTimeout(resolve, scrollingResetTimeInterval / 2);
              }));

            case 13:
              expect(cellRangeRendererCalls).toEqual(1);

            case 14:
              i++;
              _context5.next = 8;
              break;

            case 17:
              cellRangeRendererCalls = 0; // wait for real _debounceScrollEndedCallback

              _context5.next = 20;
              return _regeneratorRuntime.awrap(new Promise(function (resolve) {
                return setTimeout(resolve, scrollingResetTimeInterval * 1.5);
              }));

            case 20:
              expect(cellRangeRendererCalls).toEqual(1);

            case 21:
            case "end":
              return _context5.stop();
          }
        }
      });
    });
    it('should support a custom :scrollingResetTimeInterval prop', function _callee6(done) {
      var cellRendererCalls, scrollingResetTimeInterval, cellRenderer, props, grid;
      return _regeneratorRuntime.async(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              cellRenderer = function _ref18(_ref17) {
                var columnIndex = _ref17.columnIndex,
                    key = _ref17.key,
                    rowIndex = _ref17.rowIndex,
                    style = _ref17.style;
                cellRendererCalls.push({
                  columnIndex: columnIndex,
                  rowIndex: rowIndex
                });
                return defaultCellRenderer({
                  columnIndex: columnIndex,
                  key: key,
                  rowIndex: rowIndex,
                  style: style
                });
              };

              cellRendererCalls = [];
              scrollingResetTimeInterval = DEFAULT_SCROLLING_RESET_TIME_INTERVAL * 2;
              props = {
                cellRenderer: cellRenderer,
                scrollingResetTimeInterval: scrollingResetTimeInterval
              };
              grid = render(getMarkup(props));
              expect(cellRendererCalls.length > 0).toEqual(true);
              simulateScroll({
                grid: grid,
                scrollTop: 1
              });
              _context6.next = 9;
              return _regeneratorRuntime.awrap(new Promise(function (resolve) {
                return setTimeout(resolve, DEFAULT_SCROLLING_RESET_TIME_INTERVAL);
              }));

            case 9:
              cellRendererCalls.splice(0);
              render(getMarkup(_objectSpread({}, props, {
                className: 'foo'
              })));
              expect(cellRendererCalls.length).toEqual(0);
              _context6.next = 14;
              return _regeneratorRuntime.awrap(new Promise(function (resolve) {
                return setTimeout(resolve, DEFAULT_SCROLLING_RESET_TIME_INTERVAL * 2);
              }));

            case 14:
              cellRendererCalls.splice(0);
              render(getMarkup(_objectSpread({}, props, {
                className: 'bar'
              })));
              expect(cellRendererCalls.length).not.toEqual(0);
              done();

            case 18:
            case "end":
              return _context6.stop();
          }
        }
      });
    });
  });
  describe('measureAllCells', function () {
    it('should measure any unmeasured columns and rows', function () {
      var grid = render(getMarkup({
        columnCount: 10,
        columnWidth: function columnWidth() {
          return 100;
        },
        estimatedColumnSize: 150,
        estimatedRowSize: 15,
        height: 0,
        rowCount: 10,
        rowHeight: function rowHeight() {
          return 20;
        },
        width: 0
      }));
      expect(grid.state.instanceProps.columnSizeAndPositionManager.getTotalSize()).toEqual(1500);
      expect(grid.state.instanceProps.rowSizeAndPositionManager.getTotalSize()).toEqual(150);
      grid.measureAllCells();
      expect(grid.state.instanceProps.columnSizeAndPositionManager.getTotalSize()).toEqual(1000);
      expect(grid.state.instanceProps.rowSizeAndPositionManager.getTotalSize()).toEqual(200);
    });
  });
  describe('recomputeGridSize', function () {
    it('should recompute cell sizes and other values when called', function () {
      var columnIndices = [];
      var rowIndices = [];

      function columnWidth(_ref19) {
        var index = _ref19.index;
        columnIndices.push(index);
        return 10;
      }

      function rowHeight(_ref20) {
        var index = _ref20.index;
        rowIndices.push(index);
        return 10;
      }

      var props = {
        columnCount: 50,
        columnWidth: columnWidth,
        height: 50,
        rowHeight: rowHeight,
        rowCount: 50,
        width: 100
      };
      var component = render(getMarkup(props));
      columnIndices.splice(0);
      rowIndices.splice(0);
      component.recomputeGridSize(); // Only the rows required to fill the current viewport will be rendered

      expect(columnIndices[0]).toEqual(0);
      expect(columnIndices[columnIndices.length - 1]).toEqual(9);
      expect(rowIndices[0]).toEqual(0);
      expect(rowIndices[rowIndices.length - 1]).toEqual(4);
      columnIndices.splice(0);
      rowIndices.splice(0);
      component.recomputeGridSize({
        columnIndex: 4,
        rowIndex: 2
      }); // Only the rows required to fill the current viewport will be rendered

      expect(columnIndices[0]).toEqual(4);
      expect(columnIndices[columnIndices.length - 1]).toEqual(9);
      expect(rowIndices[0]).toEqual(2);
      expect(rowIndices[rowIndices.length - 1]).toEqual(4);
    });
  });
  describe('autoContainerWidth', function () {
    it('should set the innerScrollContainer width to auto to better support single-column HOCs', function () {
      var props = {
        autoContainerWidth: true
      };
      var rendered = findDOMNode(render(getMarkup(props)));
      expect(rendered.querySelector('.ReactVirtualized__Grid__innerScrollContainer').style.width).toEqual('auto');
    });
    it('should set the innerScrollContainer width to :totalColumnsWidth unless :autoContainerWidth', function () {
      var props = {
        autoContainerWidth: false
      };
      var rendered = findDOMNode(render(getMarkup(props)));
      expect(rendered.querySelector('.ReactVirtualized__Grid__innerScrollContainer').style.width).toEqual('2500px'); // 50 columns x 50px
    });
  });
  describe('autoHeight', function () {
    it('should set the container height to auto to adjust to innerScrollContainer height', function () {
      var props = {
        autoHeight: true
      };
      var rendered = findDOMNode(render(getMarkup(props)));
      expect(rendered.style.height).toEqual('auto');
    });
    it('should have container height still affecting number of rows rendered', function () {
      var props = {
        height: 500,
        autoHeight: true
      };
      var rendered = findDOMNode(render(getMarkup(props)));
      expect(rendered.querySelectorAll('.gridItem').length).toEqual(100); // 25 rows x 4 columns
    });
    it('should have innerScrollContainer height to be equal number of rows * rowHeight', function () {
      var props = {
        autoHeight: true
      };
      var grid = render(getMarkup(props));
      var rendered = findDOMNode(grid);
      expect(rendered.querySelector('.ReactVirtualized__Grid__innerScrollContainer').style.height).toEqual('2000px'); // 100 rows * 20px rowHeight

      expect(grid.state.instanceProps.rowSizeAndPositionManager.getTotalSize()).toEqual(2000);
    });
  });
  describe('autoWidth', function () {
    it('should set the container width to auto to adjust to innerScrollContainer width', function () {
      var props = {
        autoWidth: true
      };
      var rendered = findDOMNode(render(getMarkup(props)));
      expect(rendered.style.width).toEqual('auto');
    });
    it('should have container width still affecting number of columns rendered', function () {
      var props = {
        width: 500,
        autoWidth: true
      };
      var rendered = findDOMNode(render(getMarkup(props)));
      expect(rendered.querySelectorAll('.gridItem').length).toEqual(50); // 5 rows x 10 columns
    });
    it('should have innerScrollContainer width to be equal number of columns * columnWidth', function () {
      var props = {
        autoWidth: true
      };
      var grid = render(getMarkup(props));
      var rendered = findDOMNode(grid);
      expect(rendered.querySelector('.ReactVirtualized__Grid__innerScrollContainer').style.width).toEqual('2500px'); // 50 columns * 50px columnWidth

      expect(grid.state.instanceProps.columnSizeAndPositionManager.getTotalSize()).toEqual(2500);
    });
  });
  describe('tabIndex', function () {
    it('should be focusable by default', function () {
      var rendered = findDOMNode(render(getMarkup()));
      expect(rendered.tabIndex).toEqual(0);
    });
    it('should allow tabIndex to be overridden', function () {
      var rendered = findDOMNode(render(getMarkup({
        tabIndex: -1
      })));
      expect(rendered.tabIndex).toEqual(-1);
    });
  });
  describe('role', function () {
    it('should have grid role by default', function () {
      var rendered = findDOMNode(render(getMarkup()));
      expect(rendered.getAttribute('role')).toEqual('grid');
    });
    it('should allow role to be overridden', function () {
      var role = null;
      var rendered = findDOMNode(render(getMarkup({
        role: role
      })));
      expect(rendered.getAttribute('role')).toEqual(role);
    });
  });
  describe('pure', function () {
    it('should not re-render unless props have changed', function () {
      var cellRendererCalled = false;

      function cellRenderer(_ref21) {
        var key = _ref21.key,
            style = _ref21.style;
        cellRendererCalled = true;
        return React.createElement("div", {
          key: key,
          style: style
        });
      }

      var markup = getMarkup({
        cellRenderer: cellRenderer
      });
      render(markup);
      expect(cellRendererCalled).toEqual(true);
      cellRendererCalled = false;
      render(markup);
      expect(cellRendererCalled).toEqual(false);
    });
    it('should not re-render grid components if they extend PureComponent', function () {
      var componentUpdates = 0;

      var GridComponent =
      /*#__PURE__*/
      function (_React$PureComponent) {
        _inherits(GridComponent, _React$PureComponent);

        function GridComponent() {
          _classCallCheck(this, GridComponent);

          return _possibleConstructorReturn(this, _getPrototypeOf(GridComponent).apply(this, arguments));
        }

        _createClass(GridComponent, [{
          key: "componentDidUpdate",
          value: function componentDidUpdate() {
            componentUpdates++;
          }
        }, {
          key: "render",
          value: function render() {
            var _this$props = this.props,
                columnIndex = _this$props.columnIndex,
                rowIndex = _this$props.rowIndex,
                style = _this$props.style;
            return React.createElement("div", {
              className: "gridItem",
              style: style
            }, "row:".concat(rowIndex, ", column:").concat(columnIndex));
          }
        }]);

        return GridComponent;
      }(React.PureComponent);

      function cellRenderer(_ref22) {
        var columnIndex = _ref22.columnIndex,
            key = _ref22.key,
            rowIndex = _ref22.rowIndex,
            style = _ref22.style;
        return React.createElement(GridComponent, {
          key: key,
          columnIndex: columnIndex,
          rowIndex: rowIndex,
          style: style
        });
      }

      var props = {
        cellRenderer: cellRenderer,
        columnWidth: 100,
        height: 40,
        rowHeight: 20,
        scrollTop: 0,
        width: 100
      };
      var grid = render(getMarkup(props));
      simulateScroll({
        grid: grid,
        scrollToIndex: 1
      });
      expect(componentUpdates).toEqual(0);
    });
    it('should clear all but the visible rows from the style cache once :isScrolling is false', function _callee7(done) {
      var props, grid;
      return _regeneratorRuntime.async(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              props = {
                columnWidth: 50,
                height: 100,
                overscanColumnCount: 0,
                overscanRowCount: 0,
                rowHeight: 50,
                width: 100
              };
              grid = render(getMarkup(props));
              expect(Object.keys(grid._styleCache).length).toBe(4);
              simulateScroll({
                grid: grid,
                scrollTop: 50
              });
              expect(Object.keys(grid._styleCache).length).toBe(6); // Allow scrolling timeout to complete so that cell cache is reset

              _context7.next = 7;
              return _regeneratorRuntime.awrap(new Promise(function (resolve) {
                return setTimeout(resolve, DEFAULT_SCROLLING_RESET_TIME_INTERVAL * 2);
              }));

            case 7:
              expect(Object.keys(grid._styleCache).length).toBe(4);
              done();

            case 9:
            case "end":
              return _context7.stop();
          }
        }
      });
    });
    it('should clear style cache if :recomputeGridSize is called', function () {
      var props = {
        columnWidth: 50,
        height: 100,
        overscanColumnCount: 0,
        overscanRowCount: 0,
        rowHeight: 50,
        width: 100
      };
      var grid = render(getMarkup(props));
      expect(Object.keys(grid._styleCache).length).toBe(4);
      render(getMarkup(_objectSpread({}, props, {
        scrollTop: 50
      })));
      expect(Object.keys(grid._styleCache).length).toBe(6);
      grid.recomputeGridSize();
      expect(Object.keys(grid._styleCache).length).toBe(4);
    });
    it('should clear style cache if cell sizes change', function () {
      var cellRendererCalls = [];

      function cellRenderer(params) {
        cellRendererCalls.push(params);
        return React.createElement("div", {
          key: params.key,
          style: params.style
        });
      }

      var props = {
        cellRenderer: cellRenderer,
        columnWidth: 100,
        height: 100,
        overscanColumnCount: 0,
        overscanRowCount: 0,
        rowHeight: 100,
        width: 100
      };
      render(getMarkup(props));
      expect(cellRendererCalls.length).toEqual(1);
      expect(cellRendererCalls[0].style.width).toEqual(100);
      render(getMarkup(_objectSpread({}, props, {
        columnWidth: 50,
        width: 50
      })));
      expect(cellRendererCalls.length).toEqual(2);
      expect(cellRendererCalls[1].style.width).toEqual(50);
    });
  });
  it('should not pull from the style cache while scrolling if there is an offset adjustment', function () {
    var cellRendererCalls = [];

    function cellRenderer(params) {
      cellRendererCalls.push(params);
      return React.createElement("div", {
        key: params.key,
        style: params.style
      });
    }

    var grid = render(getMarkup({
      cellRenderer: cellRenderer,
      width: 100,
      height: 100,
      rowHeight: 100,
      columnWidth: 100,
      rowCount: getMaxElementSize() * 2 / 100,
      // lots of offset
      scrollTop: 2000
    }));
    simulateScroll({
      grid: grid,
      scrollTop: 2100
    }); // cellRendererCalls[0] is the element at rowIndex 0
    // only two calls. Since the scrollTop is updated in getDerivedStateFromProps

    var firstProps = cellRendererCalls[0];
    var secondProps = cellRendererCalls[1];
    expect(cellRendererCalls.length).toEqual(2);
    expect(firstProps.style).not.toBe(secondProps.style);
  });
  it('should only cache styles when a :deferredMeasurementCache is provided if the cell has already been measured', function () {
    var cache = new CellMeasurerCache({
      fixedWidth: true
    });
    cache.set(0, 0, 100, 100);
    cache.set(1, 1, 100, 100);
    var grid = render(getMarkup({
      columnCount: 2,
      deferredMeasurementCache: cache,
      rowCount: 2
    }));
    var keys = Object.keys(grid._styleCache);
    expect(keys).toEqual(['0-0', '1-1']);
  });
  describe('DEV warnings', function () {
    it('should warn about cells that forget to include the :style property', function () {
      spyOn(console, 'warn');

      function cellRenderer(params) {
        return React.createElement("div", {
          key: params.key
        });
      }

      render(getMarkup({
        cellRenderer: cellRenderer
      }));
      expect(console.warn).toHaveBeenCalledWith('Rendered cell should include style property for positioning.');
      expect(console.warn).toHaveBeenCalledTimes(1);
    });
    it('should warn about CellMeasurer measured cells that forget to include the :style property', function () {
      spyOn(console, 'warn');
      var cache = new CellMeasurerCache({
        fixedWidth: true
      });
      var cellRenderer = jest.fn();
      cellRenderer.mockImplementation(function (params) {
        return React.createElement(CellMeasurer, {
          cache: cache,
          columnIndex: params.columnIndex,
          key: params.key,
          parent: params.parent,
          rowIndex: params.rowIndex,
          style: params.style
        }, React.createElement("div", null));
      });
      render(getMarkup({
        cellRenderer: cellRenderer,
        columnCount: 1,
        deferredMeasurementCache: cache,
        rowCount: 1
      }));
      expect(console.warn).toHaveBeenCalledWith('Rendered cell should include style property for positioning.');
      expect(console.warn).toHaveBeenCalledTimes(1);
    });
  });
  describe('deferredMeasurementCache', function () {
    it('invalidateCellSizeAfterRender should invalidate cache and refresh displayed cells after mount', function () {
      var cache = new CellMeasurerCache({
        fixedWidth: true
      });
      var invalidateCellSizeAfterRender = true;
      var cellRenderer = jest.fn();
      cellRenderer.mockImplementation(function (params) {
        // Don't get stuck in a loop
        if (invalidateCellSizeAfterRender) {
          invalidateCellSizeAfterRender = false;
          params.parent.invalidateCellSizeAfterRender({
            columnIndex: 1,
            rowIndex: 0
          });
        }

        return React.createElement("div", {
          key: params.key,
          style: params.style
        });
      });
      var props = {
        cellRenderer: cellRenderer,
        columnCount: 2,
        deferredMeasurementCache: cache,
        rowCount: 2
      };
      render(getMarkup(props)); // 4 times for initial render + 4 once cellCache was cleared

      expect(cellRenderer).toHaveBeenCalledTimes(8);
    });
    it('should invalidate cache and refresh displayed cells after update', function () {
      var cache = new CellMeasurerCache({
        fixedWidth: true
      });
      var cellRenderer = jest.fn();
      cellRenderer.mockImplementation(function (params) {
        return React.createElement("div", {
          key: params.key,
          style: params.style
        });
      });
      var props = {
        cellRenderer: cellRenderer,
        columnCount: 2,
        deferredMeasurementCache: cache,
        rowCount: 2
      };
      var grid = render(getMarkup(props));
      expect(cellRenderer).toHaveBeenCalledTimes(4);
      var invalidateCellSizeAfterRender = false;
      cellRenderer.mockReset();
      cellRenderer.mockImplementation(function (params) {
        // Don't get stuck in a loop
        if (invalidateCellSizeAfterRender) {
          invalidateCellSizeAfterRender = false;
          params.parent.invalidateCellSizeAfterRender({
            columnIndex: 1,
            rowIndex: 0
          });
        }

        return React.createElement("div", {
          key: params.key,
          style: params.style
        });
      });
      invalidateCellSizeAfterRender = true;
      grid.recomputeGridSize(); // 4 times for initial render + 4 once cellCache was cleared

      expect(cellRenderer).toHaveBeenCalledTimes(8);
    });
    it('should not cache cells until they have been measured by CellMeasurer', function () {
      var cache = new CellMeasurerCache({
        fixedWidth: true
      }); // Fake measure cell 0,0 but not cell 0,1

      cache.set(0, 0, 100, 30);
      var cellRenderer = jest.fn();
      cellRenderer.mockImplementation(function (params) {
        return React.createElement("div", {
          key: params.key,
          style: params.style
        });
      });
      var props = {
        cellRenderer: cellRenderer,
        columnCount: 2,
        deferredMeasurementCache: cache,
        rowCount: 1
      }; // Trigger 2 renders
      // The second render should re-use the style for cell 0,0
      // But should not re-use the style for cell 0,1 since it was not measured

      var grid = render(getMarkup(props));
      grid.forceUpdate(); // 0,0 - 0,1 - 0,0 - 0,1

      expect(cellRenderer).toHaveBeenCalledTimes(4);
      var style00A = cellRenderer.mock.calls[0][0].style;
      var style01A = cellRenderer.mock.calls[1][0].style;
      var style00B = cellRenderer.mock.calls[2][0].style;
      var style01B = cellRenderer.mock.calls[3][0].style;
      expect(style00A).toBe(style00B);
      expect(style01A).not.toBe(style01B);
    });
  });
  describe('onScrollbarPresenceChange', function () {
    it('should not trigger on-mount if scrollbars are hidden', function () {
      var onScrollbarPresenceChange = jest.fn();
      render(getMarkup({
        columnCount: 1,
        getScrollbarSize: getScrollbarSize20,
        onScrollbarPresenceChange: onScrollbarPresenceChange,
        rowCount: 1
      }));
      expect(onScrollbarPresenceChange).not.toHaveBeenCalled();
    });
    it('should trigger on-mount if scrollbars are visible', function () {
      var onScrollbarPresenceChange = jest.fn();
      render(getMarkup({
        columnCount: 100,
        getScrollbarSize: getScrollbarSize20,
        onScrollbarPresenceChange: onScrollbarPresenceChange,
        rowCount: 100
      }));
      expect(onScrollbarPresenceChange).toHaveBeenCalled();
      var args = onScrollbarPresenceChange.mock.calls[0][0];
      expect(args.horizontal).toBe(true);
      expect(args.size).toBe(getScrollbarSize20());
      expect(args.vertical).toBe(true);
    });
    it('should trigger on-update if scrollbar visibility has changed', function () {
      var onScrollbarPresenceChange = jest.fn();
      render(getMarkup({
        columnCount: 1,
        getScrollbarSize: getScrollbarSize20,
        onScrollbarPresenceChange: onScrollbarPresenceChange,
        rowCount: 1
      }));
      expect(onScrollbarPresenceChange).not.toHaveBeenCalled();
      render(getMarkup({
        columnCount: 100,
        getScrollbarSize: getScrollbarSize20,
        onScrollbarPresenceChange: onScrollbarPresenceChange,
        rowCount: 100
      }));
      expect(onScrollbarPresenceChange).toHaveBeenCalled();
      var args = onScrollbarPresenceChange.mock.calls[0][0];
      expect(args.horizontal).toBe(true);
      expect(args.size).toBe(getScrollbarSize20());
      expect(args.vertical).toBe(true);
    });
    it('should not trigger on-update if scrollbar visibility does not change', function () {
      var onScrollbarPresenceChange = jest.fn();
      render(getMarkup({
        columnCount: 1,
        getScrollbarSize: getScrollbarSize20,
        onScrollbarPresenceChange: onScrollbarPresenceChange,
        rowCount: 1
      }));
      expect(onScrollbarPresenceChange).not.toHaveBeenCalled();
      render(getMarkup({
        columnCount: 2,
        getScrollbarSize: getScrollbarSize20,
        onScrollbarPresenceChange: onScrollbarPresenceChange,
        rowCount: 2
      }));
      expect(onScrollbarPresenceChange).not.toHaveBeenCalled();
    });
  });
  it('should not complain when using react-test-renderer', function () {
    var instance = TestRenderer.create(getMarkup()).getInstance();
    expect(instance).toBeTruthy();
  });
});