import { Field } from '../field/Field';
import { render, userEvent, fireEvent, screen } from '../test-utils';

import Switch from './Switch';

const props = {
  'aria-label': 'a label',
  checked: true,
  className: 'a-class-name',
  id: 'id',
  onClick: jest.fn(),
};

describe('Switch', () => {
  it('renders component when checked', () => {
    const { container } = render(
      <Switch
        aria-label={props['aria-label']}
        checked={props.checked}
        className={props.className}
        id={props.id}
        onClick={props.onClick}
      />,
    );
    expect(screen.getByRole('switch')).toBeChecked();
  });

  it('renders component associated with label', () => {
    render(
      <>
        <label id="labelID" htmlFor={props.id}>
          A switch with a label
        </label>
        <Switch
          aria-labelledby="labelID"
          checked={props.checked}
          className={props.className}
          id={props.id}
          onClick={props.onClick}
        />
        ,
      </>,
    );
    expect(screen.getByLabelText('A switch with a label')).toBeInTheDocument();
  });

  it('renders component when unchecked', () => {
    const { container } = render(
      <Switch
        checked={false}
        className={props.className}
        id={props.id}
        aria-label={props['aria-label']}
        onClick={props.onClick}
      />,
    );
    expect(screen.getByLabelText(props['aria-label'])).not.toBeChecked();
  });

  it('calls onClick when user press space or enter key', async () => {
    render(
      <Switch
        className={props.className}
        aria-label={props['aria-label']}
        onClick={props.onClick}
      />,
    );

    expect(props.onClick).not.toHaveBeenCalled();

    await userEvent.tab();

    await userEvent.keyboard(' ');
    expect(props.onClick).toHaveBeenCalledTimes(1);

    await userEvent.keyboard('{Enter}');
    expect(props.onClick).toHaveBeenCalledTimes(2);
  });

  it('should not call onClick if disabled', () => {
    const mockCallback = jest.fn();
    render(<Switch {...props} disabled onClick={mockCallback} />);
    const input = screen.getByRole('switch');
    fireEvent.click(input);
    expect(mockCallback).not.toHaveBeenCalled();
  });

  it('supports `Field` for labeling', () => {
    render(
      <Field label="Dark mode">
        <Switch checked onClick={props.onClick} />
      </Field>,
    );
    expect(screen.getByLabelText(/Dark mode/)).toHaveAttribute('role', 'switch');
  });
});
