"use strict";

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

var _enzyme = require("enzyme");

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

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

/*
Copyright (c) 2018 Uber Technologies, Inc.

This source code is licensed under the MIT license found in the
LICENSE file in the root directory of this source tree.
*/
describe('StatefulPopoverContainer', function () {
  test('basic render', function () {
    var props = {
      overrides: {
        Body: function CustomBody() {
          return _react.default.createElement("span", null);
        }
      },
      content: jest.fn(),
      onMouseEnterDelay: 100,
      onMouseLeaveDelay: 200,
      placement: _index.PLACEMENT.topLeft,
      showArrow: true,
      triggerType: _index.TRIGGER_TYPE.hover,
      dismissOnClickOutside: true,
      dismissOnEsc: true,
      initialState: {
        isOpen: true
      },
      onClose: jest.fn(),
      onOpen: jest.fn(),
      stateReducer: jest.fn()
    };
    var children = jest.fn();
    (0, _enzyme.shallow)(_react.default.createElement(_index.StatefulContainer, props, children));
    expect(children).toHaveBeenCalledTimes(1);
    expect(children.mock.calls[0]).toMatchSnapshot('function-as-child called with correct args');
  });
  test('dismissOnClickOutside', function () {
    var props = {
      content: jest.fn(),
      initialState: {
        isOpen: true
      }
    };
    var children = jest.fn();
    var component = (0, _enzyme.shallow)(_react.default.createElement(_index.StatefulContainer, props, children));
    expect(component).toHaveState('isOpen', true); // dismissOnClickOutside should default to true - onClickOutside should be set

    var propsReceived = children.mock.calls[0][0];
    expect(propsReceived.onClickOutside).toBe(component.instance().onClickOutside); // Check that onClickOutside callback properly updates component state
    // $FlowFixMe - Flow can't infer that expect() above ensures non-nullity

    propsReceived.onClickOutside();
    expect(component).toHaveState('isOpen', false); // onClickOutside should not be passed if dismissOnClickOutside is false

    component.setProps({
      dismissOnClickOutside: false
    });
    propsReceived = children.mock.calls[2][0];
    expect(propsReceived.onClickOutside).toBeUndefined();
  });
  test('dismissOnEsc', function () {
    var props = {
      content: jest.fn(),
      initialState: {
        isOpen: true
      }
    };
    var children = jest.fn();
    var component = (0, _enzyme.shallow)(_react.default.createElement(_index.StatefulContainer, props, children)); // dismissOnEsc should default to true - onEsc should be set

    var propsReceived = children.mock.calls[0][0];
    expect(propsReceived.onEsc).toBe(component.instance().onEsc); // Check that onEsc callback properly updates component state
    // $FlowFixMe - Flow can't use expect() to refine type to non-null

    propsReceived.onEsc();
    expect(component).toHaveState('isOpen', false); // onEsc should not be passed if dismissOnEsc is false

    component.setProps({
      dismissOnEsc: false
    });
    propsReceived = children.mock.calls[2][0];
    expect(propsReceived.onEsc).toBeUndefined();
  });
  test('triggerType events', function () {
    var props = {
      content: jest.fn(),
      triggerType: _index.TRIGGER_TYPE.hover
    };
    var children = jest.fn();
    var component = (0, _enzyme.shallow)(_react.default.createElement(_index.StatefulContainer, props, children)); // Should have hover-related callbacks

    var propsReceived = children.mock.calls[0][0];
    expect(propsReceived.onMouseEnter).toBe(component.instance().onMouseEnter);
    expect(propsReceived.onMouseLeave).toBe(component.instance().onMouseLeave);
    expect(propsReceived.onFocus).toBe(component.instance().onFocus);
    expect(propsReceived.onBlur).toBe(component.instance().onBlur);
    expect(propsReceived.onClick).toBeUndefined(); // $FlowFixMe - Flow can't use expect() to refine type to non-null

    propsReceived.onMouseEnter();
    expect(component).toHaveState('isOpen', true); // $FlowFixMe - Flow can't use expect() to refine type to non-null

    propsReceived.onMouseLeave();
    expect(component).toHaveState('isOpen', false); // $FlowFixMe - Flow can't use expect() to refine type to non-null

    propsReceived.onFocus();
    expect(component).toHaveState('isOpen', true); // $FlowFixMe - Flow can't use expect() to refine type to non-null

    propsReceived.onBlur();
    expect(component).toHaveState('isOpen', false); // After setting triggerType to click, should have click-related callbacks

    component.setProps({
      triggerType: _index.TRIGGER_TYPE.click
    });
    expect(children.mock.calls).toHaveLength(6);
    propsReceived = children.mock.calls[5][0];
    expect(propsReceived.onClick).toBe(component.instance().onClick);
    expect(propsReceived.onMouseEnter).toBeUndefined();
    expect(propsReceived.onMouseLeave).toBeUndefined();
    expect(propsReceived.onFocus).toBeUndefined();
    expect(propsReceived.onBlur).toBeUndefined(); // $FlowFixMe - Flow can't use expect() to refine type to non-null

    propsReceived.onClick();
    expect(component).toHaveState('isOpen', true); // $FlowFixMe - Flow can't use expect() to refine type to non-null

    propsReceived.onClick();
    expect(component).toHaveState('isOpen', false);
  });
  test('content prop receives close callback', function () {
    var props = {
      content: jest.fn(),
      initialState: {
        isOpen: true
      }
    };
    var children = jest.fn();
    var component = (0, _enzyme.shallow)(_react.default.createElement(_index.StatefulContainer, props, children));
    expect(children).toHaveBeenCalledTimes(1);
    var contentProp = children.mock.calls[0][0].content;
    expect(contentProp).toBe(component.instance().renderContent);
    component.instance().renderContent();
    expect(props.content).toHaveBeenCalledTimes(1);
    expect(props.content).toHaveBeenCalledWith({
      close: component.instance().onContentClose
    }); // $FlowFixMe - This invocation refines props.content and creates a flow error

    props.content.mock.calls[0][0].close();
    expect(component).toHaveState('isOpen', false);
  });
  test('stateReducer', function () {
    var props = {
      content: jest.fn(),
      stateReducer: jest.fn()
    };
    var children = jest.fn();
    var component = (0, _enzyme.shallow)(_react.default.createElement(_index.StatefulContainer, props, children)); // Block opening

    props.stateReducer.mockReturnValueOnce({
      isOpen: false
    });
    component.instance().onClick();
    expect(props.stateReducer).toHaveBeenCalledTimes(1);
    expect(props.stateReducer).toHaveBeenLastCalledWith(_index.STATE_CHANGE_TYPE.open, {
      isOpen: true
    }, {
      isOpen: false
    });
    expect(component).toHaveState('isOpen', false); // Open

    props.stateReducer.mockReturnValueOnce({
      isOpen: true
    });
    component.instance().onClick();
    expect(component).toHaveState('isOpen', true); // Block closing

    props.stateReducer.mockClear();
    props.stateReducer.mockReturnValueOnce({
      isOpen: true
    });
    component.instance().onClick();
    expect(props.stateReducer).toHaveBeenCalledTimes(1);
    expect(props.stateReducer).toHaveBeenLastCalledWith(_index.STATE_CHANGE_TYPE.close, {
      isOpen: false
    }, {
      isOpen: true
    });
    expect(component).toHaveState('isOpen', true);
  });
  test('onOpen/onClose callbacks', function () {
    var props = {
      onOpen: jest.fn(),
      onClose: jest.fn()
    };
    var children = jest.fn();
    var component = (0, _enzyme.shallow)(_react.default.createElement(_index.StatefulContainer, props, children));
    component.instance().onMouseEnter();
    expect(props.onOpen).toHaveBeenCalledTimes(1);
    expect(props.onClose).toHaveBeenCalledTimes(0);
    props.onOpen.mockClear();
    props.onClose.mockClear();
    component.instance().onMouseLeave();
    expect(props.onOpen).toHaveBeenCalledTimes(0);
    expect(props.onClose).toHaveBeenCalledTimes(1);
  });
  test('null stateReducer', function () {
    var props = {
      content: jest.fn(),
      stateReducer: null
    };
    var children = jest.fn();
    var component = (0, _enzyme.shallow)( // $FlowFixMe - Allow null stateReducer for the sake of testing
    _react.default.createElement(_index.StatefulContainer, props, children)); // null state reducer shouldn't break component

    component.instance().onClick();
    expect(component).toHaveState('isOpen', true);
  });
});