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; }

/*
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.
*/
import React from 'react';
import ReactDOM from 'react-dom';
import { mount } from 'enzyme';
import { KIND, PLACEMENT, toaster, ToasterContainer, Toast, StyledRoot, StyledBody, StyledCloseIcon } from '../index.js'; // Mock React 16 portals

var originalCreatePortal = ReactDOM.createPortal;
jest.useFakeTimers();
describe('toaster', function () {
  var wrapper;
  beforeAll(function () {
    // $FlowFixMe
    ReactDOM.createPortal = jest.fn(function (children) {
      return React.createElement("div", {
        "is-portal": "true",
        key: "portal"
      }, children);
    });
  });
  afterEach(function () {
    ReactDOM.createPortal.mockClear();
    wrapper && wrapper.unmount();
  });
  afterAll(function () {
    // $FlowFixMe
    ReactDOM.createPortal = originalCreatePortal;
  });
  test('ToasterContainer', function () {
    wrapper = mount(React.createElement(ToasterContainer, null));
    var renderedToaster = wrapper.find(ToasterContainer).first();
    expect(renderedToaster.instance().state.isMounted).toBe(true);
    expect(renderedToaster.instance().state.toasts.length).toEqual(0);
    expect(wrapper.find(StyledRoot).first()).toExist();
  });
  describe('ToasterContainer props', function () {
    test.each(Object.keys(PLACEMENT).map(function (pl) {
      return [pl];
    }))('%s placement is passed to the Toaster and StyledRoot component', function (placement) {
      var props = {
        placement: placement
      };
      wrapper = mount(React.createElement(ToasterContainer, props));
      expect(wrapper.find(ToasterContainer).first().props().placement).toEqual(placement);
      expect(wrapper.find(StyledRoot).first().props().$placement).toEqual(placement);
    });
    test('portal is created when usePortal is set to true', function () {
      wrapper = mount(React.createElement(ToasterContainer, null));
      expect(wrapper.find(ToasterContainer).first().props().usePortal).toBe(true);
      expect(ReactDOM.createPortal).toHaveBeenCalled();
    });
    test('portal is not created when usePortal is set to false', function () {
      wrapper = mount(React.createElement(ToasterContainer, {
        usePortal: false
      }));
      expect(wrapper.find(ToasterContainer).first().props().usePortal).toBe(false);
      expect(ReactDOM.createPortal).not.toHaveBeenCalled();
    });
  });
  describe('toaster overrides', function () {
    test('Inner components override', function () {
      var overrides = {
        Root: jest.fn().mockImplementation(function (_ref) {
          var children = _ref.children;
          return React.createElement("div", null, children);
        }),
        ToastBody: jest.fn().mockImplementation(function (_ref2) {
          var children = _ref2.children;
          return React.createElement("div", null, children);
        }),
        ToastCloseIcon: jest.fn().mockImplementation(function (_ref3) {
          var children = _ref3.children;
          return React.createElement("svg", null, children);
        })
      }; // $FlowFixMe

      wrapper = mount(React.createElement(ToasterContainer, {
        overrides: overrides
      }));
      var renderedToaster = wrapper.find(ToasterContainer).first();
      toaster.getRef = jest.fn().mockReturnValue(renderedToaster.instance());
      toaster.show('Toast message');
      wrapper.update();
      Object.keys(overrides).forEach(function (name) {
        expect(wrapper.find(overrides[name]).first()).toExist();
      });
    });
    test('Inner components props and styles overrides', function () {
      var overrides = {
        Root: {
          props: {
            'data-attr': 'root'
          },
          style: {
            borderColor: 'skyblue'
          }
        },
        ToastBody: {
          props: {
            'data-attr': 'body'
          },
          style: {
            backgroundColor: 'skyblue'
          }
        },
        ToastCloseIcon: {
          props: {
            'data-attr': 'closeIcon'
          },
          style: {
            color: 'blue'
          }
        }
      };
      var components = {
        Root: StyledRoot,
        ToastBody: StyledBody,
        ToastCloseIcon: StyledCloseIcon
      };
      wrapper = mount(React.createElement(ToasterContainer, {
        overrides: overrides
      }));
      var renderedToaster = wrapper.find(ToasterContainer).first();
      toaster.getRef = jest.fn().mockReturnValue(renderedToaster.instance());
      toaster.show('Toast message');
      wrapper.update();
      Object.keys(overrides).forEach(function (name) {
        var passedProps = wrapper.find(components[name]).first().props();
        expect(passedProps['data-attr']).toEqual(overrides[name].props['data-attr']);
        expect(passedProps.$style).toEqual(overrides[name].style);
      });
    });
  });
  describe('toaster methods', function () {
    var renderedToaster;
    beforeEach(function () {
      wrapper = mount(React.createElement(ToasterContainer, null));
      renderedToaster = wrapper.find(ToasterContainer).first();
      toaster.getRef = jest.fn().mockReturnValue(renderedToaster.instance());
    });
    test('toaster[show | update | clear]', function () {
      var toastCounter = 0;
      var toasterInstance = renderedToaster.instance(); // test toast is updated

      function getKey() {
        return "test-toast-".concat(toastCounter++);
      }

      var MockNode1 = jest.fn().mockImplementation(function () {
        return 'Toast 1';
      });
      var MockNode2 = jest.fn().mockImplementation(function () {
        return 'Toast 2';
      });
      var props1 = {
        key: getKey(),
        children: React.createElement(MockNode1, null)
      };
      var props2 = {
        key: getKey(),
        children: React.createElement(MockNode2, null)
      };
      var showSpy = jest.spyOn(toasterInstance, 'show'); // add the first Toast

      var toastKey1 = toaster.show(props1.children, {
        key: props1.key
      });
      jest.runAllTimers();
      expect(showSpy).toHaveBeenCalledTimes(1);
      expect(showSpy).toHaveBeenCalledWith(props1);
      expect(toasterInstance.state.toasts.length).toEqual(1);
      expect(toasterInstance.state.toasts[0]).toMatchObject(props1); // verify that first Toast is rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(1);
      expect(wrapper.find(StyledBody).length).toEqual(1);
      expect(wrapper.find(MockNode1).length).toEqual(1); // add the second Toast

      toaster.show(props2.children, {
        key: props2.key
      });
      jest.runAllTimers();
      expect(showSpy).toHaveBeenCalledTimes(2);
      expect(showSpy).toHaveBeenLastCalledWith(props2);
      expect(toasterInstance.state.toasts.length).toEqual(2);
      expect(toasterInstance.state.toasts[1]).toMatchObject(props2); // verify that second Toast is rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(2);
      expect(wrapper.find(StyledBody).length).toEqual(2);
      expect(wrapper.find(MockNode2).length).toEqual(1); // test toast is updated

      var updateSpy = jest.spyOn(toasterInstance, 'update');
      var MockNode3 = jest.fn().mockImplementation(function () {
        return 'Toast updated';
      });
      var updatedProps = {
        children: React.createElement(MockNode3, null),
        kind: KIND.positive
      };
      toaster.update(toastKey1, updatedProps);
      jest.runAllTimers();
      expect(updateSpy).toHaveBeenCalled();
      expect(updateSpy).toHaveBeenCalledWith(toastKey1, updatedProps);
      expect(toasterInstance.state.toasts.length).toEqual(2);
      expect(toasterInstance.state.toasts[0]).toMatchObject(_objectSpread({}, props1, updatedProps));
      expect(toasterInstance.state.toasts[1]).toMatchObject(props2); // verify that updated children are rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(2);
      expect(wrapper.find(StyledBody).length).toEqual(2);
      expect(wrapper.find(MockNode1).length).toEqual(0);
      expect(wrapper.find(MockNode3).length).toEqual(1); // test toast is cleared

      var clearSpy = jest.spyOn(toasterInstance, 'clear');
      toaster.clear(toastKey1);
      jest.runAllTimers();
      expect(clearSpy).toHaveBeenCalled();
      expect(clearSpy).toHaveBeenCalledWith(toastKey1);
      expect(toasterInstance.state.toasts.length).toEqual(1); // verify that dismissed toast is not rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(1);
      expect(wrapper.find(StyledBody).length).toEqual(1);
      expect(wrapper.find(MockNode3).length).toEqual(0);
      expect(wrapper.find(MockNode2).length).toEqual(1);
    });
    test('info, positive, warning, negative methods and clear all', function () {
      var toasterInstance = renderedToaster.instance();
      var counter = 0;
      ['info', 'positive', 'warning', 'negative'].forEach(function (method) {
        var children = "".concat(method, " toast");
        toaster[method](children);
        counter++;
        var toastsLength = toasterInstance.state.toasts.length;
        expect(toastsLength).toEqual(counter);
        expect(toasterInstance.state.toasts[toastsLength - 1]).toMatchObject({
          key: "toast-".concat(counter - 1),
          children: children,
          kind: KIND[method]
        });
      }); // verify all toasts rendered

      jest.runAllTimers();
      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(4); // verify oldest toasts are rendered last in the tree

      expect(wrapper.find(Toast).last().props()).toMatchObject({
        kind: KIND.info
      }); // verify all toasts are cleared

      var clearSpy = jest.spyOn(toasterInstance, 'clear');
      toaster.clear();
      jest.runAllTimers();
      expect(clearSpy).toHaveBeenCalled();
      expect(clearSpy).toHaveBeenCalledWith(undefined); // verify no toasts are rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(0);
    });
    test('onClose toast handler is called', function () {
      var onClose = jest.fn();
      var toastKey = toaster.show('Toast message', {
        onClose: onClose
      }); // verify the toast is rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(1); // verify the toast is cleared

      toaster.clear(toastKey);
      jest.runAllTimers(); // verify the onClose toast handler is called

      expect(onClose).toHaveBeenCalled(); // verify no toasts are rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(0);
    });
    test('toast is cleared and onClose is called when it is dismissed by a user', function () {
      var toasterInstance = renderedToaster.instance();
      var onClose = jest.fn();
      toaster.show('Toast message', {
        onClose: onClose
      }); // verify the toast is rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(1);
      var closeButton = wrapper.find(StyledCloseIcon).first();
      expect(closeButton).toExist(); // verify the toast is cleared

      closeButton.simulate('click');
      jest.runAllTimers(); // verify the toast is removed from the list

      expect(toasterInstance.state.toasts.length).toEqual(0); // verify the onClose toast handler is called

      expect(onClose).toHaveBeenCalled(); // verify no toasts are rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(0);
    });
  });
  describe('ToasterContainer autoHideDuration', function () {
    var renderedToaster;
    beforeEach(function () {
      wrapper = mount(React.createElement(ToasterContainer, {
        autoHideDuration: 100
      }));
      renderedToaster = wrapper.find(ToasterContainer).first();
      toaster.getRef = jest.fn().mockReturnValue(renderedToaster.instance());
    });
    test('info, positive, warning, negative methods receives autoHideDuration from ToastContainer', function () {
      // The testing strategy is to instatiate ToasterContainer with autoHideDuration=100
      // Then call the 4 different toaster regularly
      // Then call 1 toaster.negative with an overriding autoHideDuration=3500
      //
      // Expected outcome:
      // Initially, there should be a total of 5 Toasts
      // After jest timers get advanced by 1000, there should be 1 Toast remaining
      // After jest timers get advanced by 3000, there should be 0 Toast remaining
      var toasterInstance = renderedToaster.instance();
      var counter = 0;
      ['info', 'positive', 'warning', 'negative'].forEach(function (method) {
        var children = "".concat(method, " toast");
        toaster[method](children);
        counter++;
        var toastsLength = toasterInstance.state.toasts.length;
        expect(toastsLength).toEqual(counter);
        expect(toasterInstance.state.toasts[toastsLength - 1]).toMatchObject({
          key: "toast-".concat(counter - 1),
          children: children,
          kind: KIND[method]
        });
      });
      toaster.negative('custom autoHideDuration', {
        autoHideDuration: 3500
      }); // verify all toasts rendered

      jest.advanceTimersByTime(100);
      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(5); // verify oldest toasts are rendered last in the tree

      expect(wrapper.find(Toast).last().props()).toMatchObject({
        kind: KIND.info
      });
      jest.advanceTimersByTime(1000); // verify there's one remaining toast rendered

      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(1); // verify there's no remaining toasts rendered

      jest.advanceTimersByTime(3000);
      wrapper.update();
      expect(wrapper.find(Toast).length).toEqual(0);
    });
  });
});