import { render, screen, mockMatchMedia, userEvent, waitFor } from '../../test-utils';

import AnimatedLabel from '.';

mockMatchMedia();

const props = {
  activeLabel: 0,
  steps: [{ label: 'label1' }, { label: 'label2' }, { label: 'label3' }],
};
jest.useFakeTimers();
describe('AnimatedLabel', () => {
  it('renders only one label with class in', () => {
    const { container } = render(<AnimatedLabel {...props} />);
    expect(screen.getByText(props.steps[0].label)).toHaveClass('np-animated-label--active');
    expect(container.querySelectorAll('.np-animated-label--active')).toHaveLength(1);
  });

  it('when activeLabel increase it switches class accordingly', () => {
    const { rerender } = render(<AnimatedLabel {...props} />);
    expect(screen.getByText(props.steps[0].label)).toHaveClass('np-animated-label--active');
    expect(screen.getByText(props.steps[1].label)).not.toHaveClass('np-animated-label--active');
    expect(screen.getByText(props.steps[2].label)).not.toHaveClass('np-animated-label--active');

    rerender(<AnimatedLabel {...props} activeLabel={1} />);

    expect(screen.getByText(props.steps[0].label)).not.toHaveClass('np-animated-label--active');
    expect(screen.getByText(props.steps[1].label)).toHaveClass('np-animated-label--active');
    expect(screen.getByText(props.steps[2].label)).not.toHaveClass('np-animated-label--active');
  });

  it('when activeLabel decrease it switches class accordingly', () => {
    const { rerender } = render(<AnimatedLabel {...props} activeLabel={1} />);
    expect(screen.getByText(props.steps[0].label)).not.toHaveClass('np-animated-label--active');
    expect(screen.getByText(props.steps[1].label)).toHaveClass('np-animated-label--active');
    expect(screen.getByText(props.steps[2].label)).not.toHaveClass('np-animated-label--active');

    rerender(<AnimatedLabel {...props} activeLabel={0} />);

    expect(screen.getByText(props.steps[0].label)).toHaveClass('np-animated-label--active');
    expect(screen.getByText(props.steps[1].label)).not.toHaveClass('np-animated-label--active');
    expect(screen.getByText(props.steps[2].label)).not.toHaveClass('np-animated-label--active');
  });

  it('shows all steps in menu when click on the label', async () => {
    render(<AnimatedLabel {...props} activeLabel={1} />);
    expect(screen.queryByRole('menu')).not.toBeInTheDocument();
    userEvent.click(screen.getByRole('button', { name: /label2/i }));
    await waitFor(() => {
      expect(screen.getByRole('menu')).toBeInTheDocument();
    });
    expect(screen.getAllByRole('menuitem')).toHaveLength(props.steps.length);
  });

  it('switches label when click on one of steps as menu itme', async () => {
    const handleClick = jest.fn();
    const handleStepClick = (stepNumber) => {
      return () => handleClick(stepNumber);
    };
    render(
      <AnimatedLabel
        {...{
          activeLabel: 1,
          steps: [
            { label: 'label1', onClick: handleStepClick(0) },
            { label: 'label2', onClick: handleStepClick(1) },
            { label: 'label3', onClick: handleStepClick(2) },
          ],
        }}
      />,
    );
    expect(screen.getByRole('button', { name: /label2/i })).toBeInTheDocument();
    expect(screen.queryByRole('button', { name: /label1/i })).not.toBeInTheDocument();

    userEvent.click(screen.getByRole('button', { name: /label2/i }));

    await waitFor(() => {
      expect(screen.getByRole('menu')).toBeInTheDocument();
    });

    userEvent.click(screen.getByRole('menuitem', { name: /label1/i }));

    await waitFor(() => {
      expect(screen.queryByRole('menu')).not.toBeInTheDocument();
    });

    expect(handleClick).toHaveBeenCalledTimes(1);
    expect(handleClick).toHaveBeenCalledWith(0);
  });
});
