"use strict";

var _react = _interopRequireDefault(require("react"));

var _reactDom = _interopRequireDefault(require("react-dom"));

var _popper = _interopRequireDefault(require("popper.js"));

var _enzyme = require("enzyme");

var _index = require("../index");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

jest.useFakeTimers(); // Mock popper.js (see __mocks__ directory for impl)

jest.mock('popper.js'); // Mock React 16 portals in a way that makes them easy to test

var originalCreatePortal = _reactDom.default.createPortal; // Mock document.addEventListener

var originalDocumentAddListener = document.addEventListener;
describe('Popover', function () {
  var wrapper;
  beforeAll(function () {
    // $FlowFixMe
    _reactDom.default.createPortal = jest.fn(function (e) {
      return _react.default.createElement("div", {
        "is-portal": "true",
        key: "portal"
      }, e);
    }); // $FlowFixMe

    document.addEventListener = jest.fn();
  });
  afterEach(function () {
    _reactDom.default.createPortal.mockClear();

    document.addEventListener.mockClear();
    wrapper && wrapper.unmount();
  });
  afterAll(function () {
    // $FlowFixMe
    _reactDom.default.createPortal = originalCreatePortal; // $FlowFixMe

    document.addEventListener = originalDocumentAddListener;
  });
  test('basic click functionality', function () {
    var onClick = jest.fn();
    var onMouseEnter = jest.fn();

    var content = _react.default.createElement("strong", null, "Hello world");

    var button = _react.default.createElement("button", {
      type: "button"
    }, "Click me");

    wrapper = (0, _enzyme.mount)(_react.default.createElement(_index.Popover, {
      content: content,
      isOpen: false,
      onClick: onClick,
      onMouseEnter: onMouseEnter
    }, button)); // Should render single button child to begin

    expect(wrapper.children().length).toBe(1);
    var renderedButton = wrapper.childAt(0);
    expect(renderedButton).toHaveTagName('button');
    expect(renderedButton).toHaveText('Click me'); // Test click handling (and hover events ignored)

    renderedButton.simulate('mouseenter');
    expect(onMouseEnter).not.toBeCalled();
    renderedButton.simulate('click');
    expect(onClick).toBeCalled(); // Show the popover

    wrapper.setProps({
      isOpen: true
    }); // Should now have the portal as the second child

    expect(wrapper.children().length).toBe(2);
    expect(wrapper.childAt(0)).toHaveTagName('button');
    var portal = wrapper.childAt(1);
    expect(portal).toMatchSelector('[is-portal]'); // Portal should have the popover body and content

    var popoverBody = portal.childAt(0);
    expect(popoverBody).toMatchSelector('MockStyledComponent');
    expect(popoverBody).toHaveProp({
      $showArrow: false,
      $placement: 'auto',
      $popoverOffset: {
        top: 0,
        left: 0
      },
      $arrowOffset: {
        top: 0,
        left: 0
      },
      $isAnimating: false,
      $isOpen: true
    });
    var renderedContent = popoverBody.find('strong');
    expect(renderedContent).toExist();
    expect(renderedContent).toHaveText('Hello world'); // Popper library should have been initialized

    expect(_popper.default).toHaveBeenCalled(); // Manually emit a popper update (normally popper does this by itself)

    wrapper.instance().popper._callOnPopperUpdate();

    jest.runAllTimers();
    wrapper.update();
    popoverBody = wrapper.childAt(1).childAt(0);
    expect(popoverBody).toHaveProp({
      $placement: 'leftTop',
      $popoverOffset: {
        top: 10,
        left: 10
      },
      $arrowOffset: {
        top: 10,
        left: 10
      },
      $isAnimating: true,
      $isOpen: true
    });
  });
  test('basic mouseenter/mouseleave functionality', function () {
    var onClickButton = jest.fn();
    var onClickPopover = jest.fn();
    var onMouseEnter = jest.fn();
    var onMouseLeave = jest.fn();

    var content = _react.default.createElement("strong", null, "Hello world");

    var button = _react.default.createElement("button", {
      onClick: onClickButton,
      type: "button"
    }, "Click me");

    wrapper = (0, _enzyme.mount)(_react.default.createElement(_index.Popover, {
      content: content,
      isOpen: false,
      triggerType: "hover",
      onClick: onClickPopover,
      onMouseEnter: onMouseEnter,
      onMouseLeave: onMouseLeave,
      onMouseLeaveDelay: 200
    }, button)); // Test click handling (and hover events ignored)

    var renderedButton = wrapper.childAt(0);
    expect(renderedButton).toHaveTagName('button');
    renderedButton.simulate('mouseenter');
    jest.runAllTimers();
    expect(onMouseEnter).toBeCalled();
    expect(onMouseLeave).not.toBeCalled(); // Show the popover

    wrapper.setProps({
      isOpen: true
    }); // Portal should have the popover body and content

    var popoverBody = wrapper.childAt(1).childAt(0);
    popoverBody.simulate('mouseleave');
    expect(onMouseLeave).not.toBeCalled();
    jest.runAllTimers();
    expect(onMouseLeave).toBeCalled(); // Click should still work actually

    renderedButton.simulate('click');
    expect(onClickButton).toBeCalled();
    expect(onClickPopover).not.toBeCalled();
  });
  test('dismissOnEsc', function () {
    var onClick = jest.fn();
    var onEsc = jest.fn();

    var content = _react.default.createElement("strong", null, "Hello world");

    var button = _react.default.createElement("button", {
      type: "button"
    }, "Click me");

    wrapper = (0, _enzyme.mount)(_react.default.createElement(_index.Popover, {
      isOpen: true,
      content: content,
      onClick: onClick,
      onEsc: onEsc
    }, button));
    var calls = document.addEventListener.mock.calls;
    expect(calls[0][0]).toBe('mousedown');
    expect(calls[1][0]).toBe('keyup');
    calls[1][1]({
      key: 'Escape',
      code: 27,
      keyCode: 27
    });
    expect(onEsc).toHaveBeenCalled();
  });
  test('text as anchor', function () {
    var onClick = jest.fn();
    var onEsc = jest.fn();

    var content = _react.default.createElement("strong", null, "Hello world");

    wrapper = (0, _enzyme.mount)(_react.default.createElement(_index.Popover, {
      isOpen: true,
      content: content,
      onClick: onClick,
      onEsc: onEsc
    }, "Hover me"));
    var anchor = wrapper.childAt(0);
    expect(anchor).toHaveTagName('span');
    expect(anchor).toHaveText('Hover me');
    anchor.simulate('click');
    expect(onClick).toHaveBeenCalledTimes(1);
  });
  test('component as anchor', function () {
    var onClick = jest.fn();

    var content = _react.default.createElement("strong", null, "Hello world");

    var CustomComponent = jest.fn();
    CustomComponent.mockReturnValue(_react.default.createElement("span", null, "Hover Me"));
    wrapper = (0, _enzyme.mount)(_react.default.createElement(_index.Popover, {
      isOpen: true,
      content: content,
      onClick: onClick
    }, _react.default.createElement(CustomComponent, null)));
    expect(CustomComponent).toHaveBeenCalledTimes(1);
    expect(CustomComponent).toHaveBeenLastCalledWith({
      $ref: wrapper.instance().anchorRef,
      onClick: wrapper.instance().onAnchorClick,
      'aria-controls': null,
      'aria-haspopup': 'true',
      'aria-expanded': 'true'
    }, {});
  });
  test('component overrides', function () {
    var overrides = {
      Arrow: jest.fn().mockImplementation(function () {
        return _react.default.createElement("div", null);
      }),
      Body: jest.fn().mockImplementation(function (_ref) {
        var children = _ref.children;
        return _react.default.createElement("div", null, children);
      }),
      Inner: jest.fn().mockImplementation(function (_ref2) {
        var children = _ref2.children;
        return _react.default.createElement("div", null, children);
      })
    };
    wrapper = (0, _enzyme.mount)( // $FlowFixMe - Flow is complaining about jest mock args
    _react.default.createElement(_index.Popover, {
      isOpen: true,
      overrides: overrides,
      showArrow: true,
      triggerType: _index.TRIGGER_TYPE.hover
    }, "Hover me")); // eslint-disable-next-line flowtype/no-weak-types

    function withoutChildren(obj) {
      var shallowCopy = _objectSpread({}, obj);

      delete shallowCopy.children;
      return shallowCopy;
    }

    var body = wrapper.find(overrides.Body);
    expect(body).toHaveLength(1);
    expect(withoutChildren(body.props())).toMatchSnapshot('custom popover body has correct props');
    var arrow = wrapper.find(overrides.Arrow);
    expect(arrow).toHaveLength(1);
    expect(withoutChildren(arrow.props())).toMatchSnapshot('custom popover arrow has correct props');
    var inner = wrapper.find(overrides.Inner);
    expect(inner).toHaveLength(1);
    expect(withoutChildren(inner.props())).toMatchSnapshot('custom popover inner has correct props');
  });
  test('click accessibility attributes', function () {
    var id = 'my-custom-popover';
    wrapper = (0, _enzyme.mount)(_react.default.createElement(_index.Popover, {
      id: id,
      isOpen: false,
      content: _react.default.createElement("span", null, "Hello"),
      accessibilityType: _index.ACCESSIBILITY_TYPE.menu
    }, "Click me"));
    var anchor = wrapper.childAt(0);
    expect(anchor).toHaveProp({
      'aria-haspopup': 'true',
      'aria-expanded': 'false',
      'aria-controls': null
    });
    wrapper.setProps({
      isOpen: true
    });
    anchor = wrapper.childAt(0);
    expect(anchor).toHaveProp({
      'aria-haspopup': 'true',
      'aria-expanded': 'true',
      'aria-controls': id
    });
    var body = wrapper.find(_index.StyledBody);
    expect(body).toHaveLength(1);
    expect(body).toHaveProp({
      id: id
    });
  });
  test('hover accessibility attributes', function () {
    var id = 'my-custom-popover';
    wrapper = (0, _enzyme.mount)(_react.default.createElement(_index.Popover, {
      id: id,
      isOpen: false,
      content: _react.default.createElement("span", null, "Hello"),
      accessibilityType: _index.ACCESSIBILITY_TYPE.menu,
      triggerType: _index.TRIGGER_TYPE.hover
    }, "Hover me"));
    var anchor = wrapper.childAt(0);
    expect(anchor).toHaveProp({
      'aria-haspopup': 'true',
      'aria-expanded': 'false',
      'aria-owns': null
    });
    wrapper.setProps({
      isOpen: true
    });
    anchor = wrapper.childAt(0);
    expect(anchor).toHaveProp({
      'aria-haspopup': 'true',
      'aria-expanded': 'true',
      'aria-owns': id
    });
    var body = wrapper.find(_index.StyledBody);
    expect(body).toHaveLength(1);
    expect(body).toHaveProp({
      id: id
    });
  });
  test('tooltip accessibility attributes', function () {
    var id = 'my-custom-popover';
    wrapper = (0, _enzyme.mount)(_react.default.createElement(_index.Popover, {
      id: id,
      isOpen: false,
      content: _react.default.createElement("span", null, "Hello"),
      accessibilityType: _index.ACCESSIBILITY_TYPE.tooltip,
      triggerType: _index.TRIGGER_TYPE.hover
    }, "Hover me"));
    var anchor = wrapper.childAt(0);
    expect(anchor).toHaveProp({
      id: "".concat(id, "__anchor"),
      'aria-describedby': null
    });
    wrapper.setProps({
      isOpen: true
    });
    anchor = wrapper.childAt(0);
    expect(anchor).toHaveProp({
      id: "".concat(id, "__anchor"),
      'aria-describedby': id
    });
    var body = wrapper.find(_index.StyledBody);
    expect(body).toHaveLength(1);
    expect(body).toHaveProp({
      id: id,
      role: 'tooltip'
    });
  });
});