"use strict";

var _react = require("@testing-library/react");
var _useTableKeyboardNavigation = require("./useTableKeyboardNavigation");
describe('useTableKeyboardNavigation', function () {
  const cellRefMock = {
    current: {
      focus: jest.fn(),
      setAttribute: jest.fn()
    }
  };
  const defaultCellActionMock = jest.fn();
  function initHook(colsCount = 3, rowsCount = 3, activeElementIsWithin = true) {
    // eslint-disable-next-line testing-library/render-result-naming-convention
    const hook = (0, _react.renderHook)(() => (0, _useTableKeyboardNavigation.useTableKeyboardNavigation)({
      tableRef: {
        current: {
          contains: jest.fn(() => activeElementIsWithin)
        }
      },
      rowsCount,
      columnsCount: colsCount
    }));

    // in table we use -1 for header row not to mess around with virtual indexes, so here we need to mimic that logic too
    for (let columnIndex = 0; columnIndex < colsCount; columnIndex++) {
      for (let rowIndex = -1; rowIndex + 1 < rowsCount; rowIndex++) {
        hook.result.current.registerCell({
          cellRowIndex: rowIndex,
          cellColumnIndex: columnIndex,
          cellRef: cellRefMock,
          cellAction: defaultCellActionMock
        });
      }
    }
    return hook;
  }
  beforeEach(function () {
    // we have to mock activeElement so that checks to perform action would pass
    jest.spyOn(document, 'activeElement', 'get').mockReturnValue(cellRefMock.current);
  });
  afterEach(function () {
    jest.resetAllMocks();
  });
  it('should register cells and invoke focus function', function () {
    const hook = initHook();
    (0, _react.act)(() => hook.result.current.setFocusedCell('0-0'));
    expect(hook.result.current.focusedCell).toEqual('0-0');
  });
  it('should change focused cell via keyboard events', function () {
    const hook = initHook();
    (0, _react.act)(() => hook.result.current.setFocusedCell('-1-0'));
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'ArrowDown'
    })));
    expect(hook.result.current.focusedCell).toEqual('0-0');
    expect(cellRefMock.current.focus).toHaveBeenCalled();
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'ArrowRight'
    })));
    expect(hook.result.current.focusedCell).toEqual('0-1');
    expect(cellRefMock.current.focus).toHaveBeenCalledTimes(2);
  });
  it('should not react to keyboard event if focusedCell is not set', function () {
    const hook = initHook();
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'ArrowDown'
    })));
    expect(hook.result.current.focusedCell).toBeUndefined();
    expect(cellRefMock.current.focus).not.toHaveBeenCalled();
  });
  it('should not react to keyboard events if none cells were registered', function () {
    const hook = initHook(0, 0);
    (0, _react.act)(() => hook.result.current.setFocusedCell('0-0'));
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'ArrowDown'
    })));
    expect(hook.result.current.focusedCell).toEqual('0-0');
    expect(cellRefMock.current.focus).not.toHaveBeenCalled();
  });
  it('should not react to keyboard events if active element is not within table', function () {
    const hook = initHook(2, 2, false);
    (0, _react.act)(() => hook.result.current.setFocusedCell('0-0'));
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'ArrowDown'
    })));
    expect(hook.result.current.focusedCell).toEqual('0-0');
    expect(cellRefMock.current.focus).not.toHaveBeenCalled();
  });
  it('should not change focused cell for edge cells', function () {
    const hook = initHook(2, 2);

    // can't go up from the first row
    (0, _react.act)(() => hook.result.current.setFocusedCell('-1-0'));
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'ArrowUp'
    })));
    expect(hook.result.current.focusedCell).toEqual('-1-0');
    expect(cellRefMock.current.focus).not.toHaveBeenCalled();

    // can't go right from the last column
    (0, _react.act)(() => hook.result.current.setFocusedCell('-1-1'));
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'ArrowRight'
    })));
    expect(hook.result.current.focusedCell).toEqual('-1-1');
    expect(cellRefMock.current.focus).not.toHaveBeenCalled();

    // can't go down from the last row
    (0, _react.act)(() => hook.result.current.setFocusedCell('0-0'));
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'ArrowDown'
    })));
    expect(hook.result.current.focusedCell).toEqual('0-0');
    expect(cellRefMock.current.focus).not.toHaveBeenCalled();

    // can't go left from the first column
    (0, _react.act)(() => hook.result.current.setFocusedCell('0-0'));
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'ArrowLeft'
    })));
    expect(hook.result.current.focusedCell).toEqual('0-0');
    expect(cellRefMock.current.focus).not.toHaveBeenCalled();
  });
  it('should invoke action function on Enter press', async function () {
    const hook = initHook(2, 2);
    (0, _react.act)(() => hook.result.current.setFocusedCell('0-0'));
    expect(hook.result.current.focusedCell).toEqual('0-0');
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'Enter'
    })));
    await (0, _react.waitFor)(() => {
      expect(defaultCellActionMock).toHaveBeenCalled();
    });
  });
  it('should invoke custom cell action if on is registered', async function () {
    const customCellActionMock = jest.fn();
    const hook = initHook(2, 2);
    (0, _react.act)(() => hook.result.current.setFocusedCell('0-0'));
    expect(hook.result.current.focusedCell).toEqual('0-0');
    hook.result.current.registerCustomCellAction('0-0', customCellActionMock);
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'Enter'
    })));
    await (0, _react.waitFor)(() => {
      expect(customCellActionMock).toHaveBeenCalled();
    });
    expect(defaultCellActionMock).not.toHaveBeenCalled();
  });
  it('should move to the first/last cell of the row using "Home"/"End" buttons', function () {
    const hook = initHook();
    (0, _react.act)(() => hook.result.current.setFocusedCell('0-0'));
    expect(hook.result.current.focusedCell).toEqual('0-0');
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'End'
    })));
    expect(hook.result.current.focusedCell).toEqual('0-2');
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'Home'
    })));
    expect(hook.result.current.focusedCell).toEqual('0-0');
  });
  it('should move to the first/last available row with use of "PageUp"/"PageDown"', function () {
    const hook = initHook();
    (0, _react.act)(() => hook.result.current.setFocusedCell('0-0'));
    expect(hook.result.current.focusedCell).toEqual('0-0');
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'PageDown'
    })));
    expect(hook.result.current.focusedCell).toEqual('1-0');
    (0, _react.act)(() => hook.result.current.onTableKeyDownHandler(new KeyboardEvent('keydown', {
      key: 'PageUp'
    })));
    expect(hook.result.current.focusedCell).toEqual('0-0');
  });
});