import { render, fireEvent, cleanup, screen, mockMatchMedia } from '../test-utils';

import Nudge from '.';

mockMatchMedia();

describe('Nudge', () => {
  const defaultProps = {
    title: 'A nudge title',
    link: 'CTA',
    href: '#',
    onClick: jest.fn(),
    onDismiss: jest.fn(),
  };

  afterEach(cleanup);

  it('renders a title', () => {
    render(<Nudge {...defaultProps} />);
    const title = screen.getByText('A nudge title');
    expect(title).toBeInTheDocument();
  });

  it('renders a link to the passed href', () => {
    render(<Nudge {...defaultProps} />);
    const link = screen.getByText('CTA');
    expect(link).toBeInTheDocument();
    expect(link).toHaveAttribute('href', defaultProps.href);
  });

  it('calls onClick prop when the link is clicked', () => {
    render(<Nudge {...defaultProps} />);
    const link = screen.getByText('CTA');
    fireEvent.click(link);
    expect(defaultProps.onClick).toHaveBeenCalledTimes(1);
  });

  it('calls onDismiss prop when close button is clicked', () => {
    render(<Nudge {...defaultProps} />);
    const closeButton = screen.getByLabelText('Close');
    fireEvent.click(closeButton);
    expect(defaultProps.onDismiss).toHaveBeenCalledTimes(1);
  });

  describe('Nudge persistance', () => {
    beforeEach(() => {
      jest.resetAllMocks();
    });

    it('does NOT render a nudge if localStorage has been set with the id of the nudge', () => {
      jest.spyOn(Storage.prototype, 'getItem').mockReturnValue('["CAKE","TEST"]');

      render(<Nudge {...defaultProps} id="TEST" persistDismissal />);
      expect(screen.queryByText('A nudge title')).not.toBeInTheDocument();
    });

    it('does NOT render a nudge if localStorage has been set with the id of the nudge AND calls is previously dismissed with TRUE', () => {
      jest.spyOn(Storage.prototype, 'getItem').mockReturnValue('["CAKE","TEST"]');
      const isPreviouslyDismissed = jest.fn();

      render(
        <Nudge
          {...defaultProps}
          id="TEST"
          persistDismissal
          isPreviouslyDismissed={isPreviouslyDismissed}
        />,
      );

      expect(screen.queryByText('A nudge title')).not.toBeInTheDocument();
      expect(isPreviouslyDismissed).toHaveBeenCalledWith(true);
    });

    it('shows a nudge if localStorage has been set with a different id for a different nudge and calls is previously dismissed with FALSE', () => {
      mockMatchMedia();
      jest.spyOn(Storage.prototype, 'getItem').mockReturnValue('["BANANA"]');
      const isPreviouslyDismissed = jest.fn();

      render(
        <Nudge
          {...defaultProps}
          id="TEST"
          persistDismissal
          isPreviouslyDismissed={isPreviouslyDismissed}
        />,
      );

      expect(screen.getByText('A nudge title')).toBeInTheDocument();
      expect(isPreviouslyDismissed).toHaveBeenCalledWith(false);
    });

    it('calls local storage with updated dismissed nudges value', () => {
      mockMatchMedia();
      jest.spyOn(Storage.prototype, 'getItem').mockReturnValue('["BANANA"]');
      const setItem = jest.spyOn(Storage.prototype, 'setItem');

      render(<Nudge {...defaultProps} id="TEST" persistDismissal />);
      expect(screen.getByText('A nudge title')).toBeInTheDocument();

      const closeButton = screen.getByLabelText('Close');
      fireEvent.click(closeButton);

      expect(defaultProps.onDismiss).toHaveBeenCalledTimes(1);
      expect(setItem).toHaveBeenCalledWith('dismissedNudges', '["BANANA","TEST"]');
    });
  });
});
