// @flow
import React from 'react';
import {
  mountWrappedComponent,
  getFakeComponent,
  noop,
  renderSnapshot,
} from '../../../../../utils/tests';

import type { ToastProps } from './toast.proptypes';
import { Toast, CloseButton, StyledToast } from './index';

const DEFAULT_PROPS: ToastProps = {
  id: 'great-id',
  timerDelay: 200,
  onClose: noop,
};

beforeEach(() => {
  jest.useFakeTimers();
});

afterEach(() => {
  jest.clearAllTimers();
});

describe('Toast', () => {
  describe('snapshot', () => {
    it('matches the previous snapshot', () => {
      const toast = renderSnapshot(
        <Toast {...DEFAULT_PROPS}>{getFakeComponent('toast')}</Toast>,
      );
      expect(toast).toMatchSnapshot();
    });
  });

  describe('Timers', () => {
    it('starts timeout when mounted', () => {
      mountWrappedComponent(
        <Toast {...DEFAULT_PROPS}>{getFakeComponent('toast')}</Toast>,
      );

      expect(window.setTimeout).toHaveBeenLastCalledWith(
        expect.any(Function),
        DEFAULT_PROPS.timerDelay,
      );
    });

    it('clears timeout when focused', () => {
      const toast = mountWrappedComponent(
        <Toast {...DEFAULT_PROPS}>{getFakeComponent('toast')}</Toast>,
      );

      expect(window.clearTimeout).toHaveBeenCalledTimes(0);

      toast.find(StyledToast).simulate('focus');

      expect(window.clearTimeout).toHaveBeenCalledTimes(1);
      expect(window.clearTimeout).toHaveBeenLastCalledWith(expect.any(Number));
    });

    it('sets timeout when blurred', () => {
      const toast = mountWrappedComponent(
        <Toast {...DEFAULT_PROPS}>{getFakeComponent('toast')}</Toast>,
      );

      expect(window.clearTimeout).toHaveBeenCalledTimes(0);

      toast.find(StyledToast).simulate('blur');

      expect(window.setTimeout).toHaveBeenCalled();
      expect(window.setTimeout).toHaveBeenLastCalledWith(
        expect.any(Function),
        DEFAULT_PROPS.timerDelay,
      );
    });
  });

  describe('Close Button', () => {
    it('renders with valid props', () => {
      const toast = mountWrappedComponent(
        <Toast {...DEFAULT_PROPS}>{getFakeComponent('toast')}</Toast>,
      );

      expect(toast.find(CloseButton).props()).toEqual({
        insetFocus: true,
        onFocus: expect.any(Function),
        onBlur: expect.any(Function),
        onClick: expect.any(Function),
        children: expect.anything(),
      });
    });

    it('closes toast when clicked', async () => {
      const handleOnClose = jest.fn();
      const toast = mountWrappedComponent(
        <Toast {...DEFAULT_PROPS} onClose={handleOnClose}>
          {getFakeComponent('toast')}
        </Toast>,
      );

      expect(handleOnClose).toHaveBeenCalledTimes(0);
      const button = toast.find('CloseButton');

      button.simulate('click');

      await toast.update();

      expect(handleOnClose).toHaveBeenCalledWith(DEFAULT_PROPS.id);
    });
  });
});
