import { Position } from '../common';
import { render, screen, userEvent } from '../test-utils';

import Card from '.';

describe('Card', () => {
  const defaultProps = {
    title: 'A Card',
    details: 'Some details about this card',
    icon: <svg />,
    isExpanded: false,
    onClick: jest.fn(),
  };
  const dataTestId = 'testCard';
  const renderCard = (props = {}) => {
    return render(<Card {...defaultProps} {...props} />);
  };

  it('renders as a div by default', () => {
    renderCard({ 'data-testid': dataTestId });
    expect(screen.getByTestId(dataTestId).tagName).toBe('DIV');
  });

  it('renders as a tag passed to it', () => {
    renderCard({ as: 'li', 'data-testid': dataTestId });
    expect(screen.getByTestId(dataTestId).tagName).toBe('LI');
  });

  it('adds the passed id to the card element', () => {
    const id = 'card-id';
    renderCard({ id, 'data-testid': dataTestId });
    expect(screen.getByTestId(dataTestId).id).toBe(id);
  });

  it('adds the passed className to the card element', () => {
    const className = 'card-class';
    renderCard({ className, 'data-testid': dataTestId });
    expect(screen.getByTestId(dataTestId)).toHaveClass(className);
  });

  it('renders the card title', () => {
    renderCard();
    expect(screen.getByText(defaultProps.title)).toBeInTheDocument();
  });

  it('renders the card details', () => {
    renderCard();
    expect(screen.getByText(defaultProps.details)).toBeInTheDocument();
  });

  it('renders the card icon', () => {
    renderCard({ icon: <span>mock icon</span> });
    expect(screen.getByText('mock icon')).toBeInTheDocument();
  });

  describe('when there is no children prop', () => {
    it('renders Option title as a heading 4', () => {
      const onClick = jest.fn();
      renderCard(onClick);

      expect(screen.queryByRole('button')).not.toBeInTheDocument();
      expect(screen.getByText(defaultProps.title).tagName).toBe('H4');
    });

    it('has an inactive class', () => {
      renderCard({ 'data-testid': dataTestId });

      expect(screen.getByTestId(dataTestId)).toHaveClass('np-card--inactive');
    });

    it("doesn't call onClick when clicked", async () => {
      renderCard();

      await userEvent.click(screen.getByText(defaultProps.title));

      expect(defaultProps.onClick).not.toHaveBeenCalled();
    });

    it("doesn't render a chevron", () => {
      renderCard();

      expect(screen.queryByTestId('mock-chevron')).not.toBeInTheDocument();
    });
  });

  describe('when there is children prop', () => {
    it('calls on onClick with inverse of current isExpanded value when clicked', async () => {
      const onClick = jest.fn();
      renderCard({
        'aria-label': 'test',
        title: 'test title',
        children: 'mock children',
        isExpanded: false,
        onClick,
      });

      await userEvent.click(screen.getByRole('button', { name: 'test' }));
      expect(onClick).toHaveBeenCalledWith(true);
    });

    it('renders a chevron', () => {
      renderCard({ children: 'mock children' });

      expect(screen.getByTestId('chevron-up-icon')).toHaveClass(Position.BOTTOM);
    });

    describe('when collapsed', () => {
      const CONTENT = 'mock children';

      it('should not render children', async () => {
        renderCard({ children: CONTENT });
        expect(screen.queryByText(CONTENT)).not.toBeInTheDocument();
      });

      it('should render appropriate aria attributes', async () => {
        renderCard({ children: CONTENT });
        const button = screen.getByRole('button');
        expect(button).toHaveAttribute('aria-expanded', 'false');
        expect(button).not.toHaveAttribute('aria-controls');
      });
    });

    describe('when expanded', () => {
      const defaultProps = {
        children: 'mock children',
        isExpanded: true,
      };

      it('flips chevron', () => {
        renderCard(defaultProps);

        expect(screen.getByTestId('chevron-up-icon')).toHaveClass(Position.TOP);
      });

      it('renders children', () => {
        renderCard(defaultProps);

        expect(screen.getByText(defaultProps.children)).toBeInTheDocument();
      });

      it('should render appropriate aria attributes', async () => {
        const { container } = renderCard(defaultProps);
        const button = screen.getByRole('button');
        const controlledId = button.getAttribute('aria-controls');
        expect(button).toHaveAttribute('aria-expanded', 'true');

        const contentId = screen.getByText(defaultProps.children).getAttribute('id');
        expect(contentId).toBe(controlledId);
      });
    });
  });
});
