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

import StatusIcon, { StatusIconProps } from '.';

mockMatchMedia();

describe('StatusIcon', () => {
  const renderStatusIcon = (props?: {
    sentiment?: StatusIconProps['sentiment'];
    size?: StatusIconProps['size'];
    iconLabel?: StatusIconProps['iconLabel'];
  }) => {
    return render(
      <StatusIcon
        sentiment={props?.sentiment || Sentiment.NEUTRAL}
        size={props?.size || Size.MEDIUM}
        iconLabel={props?.iconLabel}
      />,
    );
  };

  afterEach(cleanup);

  it('renders the status icon without any props', () => {
    renderStatusIcon();

    expect(screen.getByTestId('status-icon')).toHaveClass('neutral');
    expect(screen.getByTestId('status-icon')).toHaveClass('status-circle');
    expect(screen.getByTestId('status-icon')).toHaveClass('status-circle-md');
  });

  it.each([
    [Size.SMALL as const, 'status-circle-sm'],
    [Size.MEDIUM as const, 'status-circle-md'],
    [Size.LARGE as const, 'status-circle-lg'],
  ])(
    "if prop 'size' equals '%s' is passed, renders the status icon with class '%s'",
    (size, expectedClass) => {
      renderStatusIcon({ size });

      expect(screen.getByTestId('status-icon')).toHaveClass(expectedClass);
      cleanup();
    },
  );

  it.each([
    [Sentiment.NEGATIVE, Sentiment.NEGATIVE],
    [Sentiment.NEUTRAL, Sentiment.NEUTRAL],
    [Sentiment.PENDING, Sentiment.PENDING],
    [Sentiment.POSITIVE, Sentiment.POSITIVE],
    [Sentiment.WARNING, Sentiment.WARNING],
  ])(
    "if prop 'sentiment' equals '%s' is passed, renders the status icon with class '%s'",
    (sentiment, expectedClass) => {
      renderStatusIcon({ sentiment });

      expect(screen.getByTestId('status-icon')).toHaveClass(expectedClass);
      cleanup();
    },
  );

  it("'warning' and 'pending' sentiments generate 'dark' colored icons", () => {
    renderStatusIcon({ sentiment: Sentiment.WARNING });
    expect(screen.getByTestId('alert-icon')).toHaveClass('dark');
    cleanup();

    renderStatusIcon({ sentiment: Sentiment.PENDING });
    expect(screen.getByTestId('clock-borderless-icon')).toHaveClass('dark');
  });

  it("'positive', 'negative', and 'neutral' sentiments generate 'light' colored icons", () => {
    renderStatusIcon({ sentiment: Sentiment.POSITIVE });
    expect(screen.getByTestId('check-icon')).toHaveClass('light');
    cleanup();

    renderStatusIcon({ sentiment: Sentiment.NEGATIVE });
    expect(screen.getByTestId('cross-icon')).toHaveClass('light');
    cleanup();

    renderStatusIcon();
    expect(screen.getByTestId('info-icon')).toHaveClass('light');
  });

  describe('accessible name', () => {
    it.each([
      ['Error', Sentiment.NEGATIVE],
      ['Success', Sentiment.POSITIVE],
      ['Warning', Sentiment.WARNING],
      ['Pending', Sentiment.PENDING],
      ['Information', Sentiment.NEUTRAL],
      ['Error', Sentiment.ERROR],
      ['Information', Sentiment.INFO],
      ['Success', Sentiment.SUCCESS],
    ])("should set '%s' as an accessible name for the '%s' sentiment", (label, sentiment) => {
      renderStatusIcon({ sentiment });

      expect(screen.getByLabelText(`${label}:`)).toBeInTheDocument();
    });

    it('should allow for `iconLabel` overrides', () => {
      const iconLabel = 'Custom label';
      renderStatusIcon({ sentiment: Sentiment.NEGATIVE, iconLabel });

      expect(screen.getByLabelText(iconLabel)).toBeInTheDocument();
      expect(screen.queryByLabelText(`Error:`)).not.toBeInTheDocument();
    });

    it('should allow for `iconLabel` to be `null` to keep the icon presentational', () => {
      const iconLabel = null;
      renderStatusIcon({ sentiment: Sentiment.NEGATIVE, iconLabel });

      expect(screen.queryByRole(`graphics-symbol`)).not.toBeInTheDocument();
      expect(screen.queryByLabelText(`Error:`)).not.toBeInTheDocument();
    });
  });
});
