// @flow
import React from 'react';
import { mountWrappedComponent } from '../../../../utils/tests';
import { FormSelect } from './select.css-rules';
import type { SelectProps } from './select.proptypes';
import { Select } from './index';
import { Option } from './option';

const DEFAULT_PROPS: SelectProps<number> = {
  children: [<Option value={1}>First</Option>],
  disabled: false,
  error: false,
  large: false,
  onBlur: jest.fn(),
  onChange: jest.fn(),
  onFocus: jest.fn(),
  placeholder: 'placeholder',
  value: undefined,
  label: 'Label',
};

describe('Select', () => {
  it('renders a placeholder option if given a valid placeholder prop', () => {
    const placeholderMessage = 'testing';
    const select = mountWrappedComponent(
      <Select {...DEFAULT_PROPS} placeholder={placeholderMessage}>
        <Option value={1}>First option</Option>
        <Option value={2}>Second option</Option>
      </Select>,
    );

    const options = select.find('option');
    const placeholder = options.at(0);

    expect(placeholder.text()).toBe(placeholderMessage);
  });

  it('passes valid props into select', () => {
    const select = mountWrappedComponent(
      <Select {...DEFAULT_PROPS} value={1}>
        <Option value={1}>First option</Option>
        <Option value={2}>Second option</Option>
      </Select>,
    );

    expect(select.find(FormSelect).props()).toEqual(
      expect.objectContaining({
        large: DEFAULT_PROPS.large,
        disabled: DEFAULT_PROPS.disabled,
        error: DEFAULT_PROPS.error,
        value: 1,
        onBlur: DEFAULT_PROPS.onBlur,
        onChange: expect.any(Function),
        onFocus: DEFAULT_PROPS.onFocus,
        children: expect.anything(),
        id: expect.any(String),
      }),
    );
  });

  it('call onChange with the change event value', () => {
    const handleOnClick = jest.fn();
    const event = { target: { value: 'some-great-value' } };
    const select = mountWrappedComponent(
      <Select {...DEFAULT_PROPS} onChange={handleOnClick}>
        <Option value={1}>First option</Option>
        <Option value={2}>Second option</Option>
      </Select>,
    );

    select.find(FormSelect).simulate('change', event);

    expect(handleOnClick).toHaveBeenCalledTimes(1);
    expect(handleOnClick).toHaveBeenCalledWith(event.target.value);
  });

  it('shows the label that is passed', () => {
    const label = 'TESTING LABEL';
    const select = mountWrappedComponent(
      <Select {...DEFAULT_PROPS} label={label}>
        <Option value={1}>First option</Option>
        <Option value={2}>Second option</Option>
      </Select>,
    );

    expect(select.text()).toContain(label);
  });

  describe('when value is undefined', () => {
    const propsWithUndefinedValue = {
      ...DEFAULT_PROPS,
      value: undefined,
    };

    describe('when a placeholder is defined', () => {
      const select = mountWrappedComponent(
        <Select {...propsWithUndefinedValue} placeholder="Placeholder">
          <Option value={1}>First option</Option>
          <Option value={2}>Second option</Option>
        </Select>,
      );

      it('has a FormSelect value of "UNDEFINED"', () => {
        expect(select.find(FormSelect).prop('value')).toEqual('UNDEFINED');
      });
    });

    describe('when a placeholder is not defined', () => {
      const select = mountWrappedComponent(
        <Select {...propsWithUndefinedValue} placeholder={undefined}>
          <Option value={1}>First option</Option>
          <Option value={2}>Second option</Option>
        </Select>,
      );

      it('has a FormSelect value of undefined', () => {
        expect(select.find(FormSelect).prop('value')).toEqual(undefined);
      });
    });
  });
});
