import * as React from 'react';
import { shallow } from 'enzyme';
import { cleanup } from 'react-testing-library';
import 'jest-styled-components';
import { InputDropDownDrawer } from '../../../components/InputDropDownDrawer';
import { DropDownDrawer } from '../../../components/InputDropDownDrawer/DropDownDrawer';

beforeEach(cleanup);

describe('Input Drop Down Drawer', () => {
    const animals = [
        { id: 1, toString: () => 'Bear' },
        { id: 2, toString: () => 'Cat' },
        { id: 3, toString: () => 'Dog' },
        { id: 4, toString: () => 'Elefant' },
        { id: 5, toString: () => 'Lion' },
        { id: 6, toString: () => 'Sea Lion' },
        { id: 7, toString: () => 'Shark' }
    ];

    test('01 - List of options with a value and showDropDown in true displays all the options', () => {
        const wrapper = shallow(<InputDropDownDrawer
            inputValue={'Bea'}
            onDropDownEvent={(event, show: boolean) => { }}
            onSelectOption={(option: { toString: () => string }) => { }}
            showDropDown={true}
            suggestOptions={animals}
        />);

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.find('.input-drop-down-drawer-container').length).toBe(1);
        expect(wrapper.find('.input-drop-down-drawer-input-wrapper').length).toBe(1);
        expect(wrapper.find('.input-drop-down-drawer-input').length).toBe(1);
        expect(wrapper.find('.input-drop-down-drawer-input-select-icon').length).toBe(0);

        const dropDownDrawerComponent = wrapper.find(DropDownDrawer);
        expect(dropDownDrawerComponent.length).toBe(1);
        expect(dropDownDrawerComponent.props().options).toBe(animals);
    });
    test('02 - Arrow down will refresh set the next option as selected and call onDropDownEvent', () => {
        const onDropDownEvent = jest.fn();
        const wrapper = shallow(<InputDropDownDrawer
            inputValue={''}
            onDropDownEvent={onDropDownEvent}
            onSelectOption={(option: { toString: () => string }) => { }}
            showDropDown={true}
            suggestOptions={animals}
        />);

        const mockedEventKey = 'ArrowDown';
        wrapper.find('.input-drop-down-drawer-container').simulate('keyDown', {
            key: mockedEventKey
        });

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().selectedOption).toBe(1);
        expect(onDropDownEvent).toHaveBeenCalledWith({ key: mockedEventKey }, true);
    });
    test('03 - Arrow up will refresh set the previous option as selected and call onDropDownEvent', () => {
        const onDropDownEvent = jest.fn();
        const wrapper = shallow(<InputDropDownDrawer
            inputValue={''}
            onDropDownEvent={onDropDownEvent}
            onSelectOption={(option: { toString: () => string }) => { }}
            showDropDown={false}
            suggestOptions={animals}
        />);

        const mockedEventKey = 'ArrowUp';
        wrapper.find('.input-drop-down-drawer-container').simulate('keyDown', {
            key: mockedEventKey
        });

        expect(wrapper).toMatchSnapshot();
        expect(wrapper.state().selectedOption).toBe(animals.length - 1);
        expect(onDropDownEvent).toHaveBeenCalledWith({ key: mockedEventKey }, true);
    });
    test('04 - Enter when showing the dropdown will notify the selected option', () => {
        const onEnterKeyPressed = jest.fn();
        const onSelectOption = jest.fn();
        const wrapper = shallow(<InputDropDownDrawer
            inputValue={''}
            onDropDownEvent={(event, show: boolean) => { }}
            onEnterKeyPressed={onEnterKeyPressed}
            onSelectOption={onSelectOption}
            showDropDown={true}
            suggestOptions={animals}
        />);

        wrapper.find('.input-drop-down-drawer-container').simulate('keyDown', {
            key: 'Enter'
        });

        expect(wrapper).toMatchSnapshot();
        expect(onSelectOption).toHaveBeenCalledWith(animals[0]);
        expect(onEnterKeyPressed).not.toHaveBeenCalled();
    });
    test('05 - Enter when not showing the dropdown will notify the Enter event', () => {
        const onEnterKeyPressed = jest.fn();
        const onSelectOption = jest.fn();
        const wrapper = shallow(<InputDropDownDrawer
            inputValue={''}
            onDropDownEvent={(event, show: boolean) => { }}
            onEnterKeyPressed={onEnterKeyPressed}
            onSelectOption={onSelectOption}
            showDropDown={false}
            suggestOptions={animals}
        />);

        wrapper.find('.input-drop-down-drawer-container').simulate('keyDown', {
            key: 'Enter'
        });

        expect(wrapper).toMatchSnapshot();
        expect(onSelectOption).not.toHaveBeenCalled();
        expect(onEnterKeyPressed).toHaveBeenCalled();
    });
    test('06 - Escape when showing the dropdown will call onDropDownEvent', () => {
        const onDropDownEvent = jest.fn();
        const wrapper = shallow(<InputDropDownDrawer
            inputValue={''}
            onDropDownEvent={onDropDownEvent}
            onSelectOption={(option: { toString: () => string }) => { }}
            showDropDown={true}
            suggestOptions={animals}
        />);

        const mockedEventKey = 'Escape';
        wrapper.find('.input-drop-down-drawer-container').simulate('keyDown', {
            key: mockedEventKey
        });

        expect(wrapper).toMatchSnapshot();
        expect(onDropDownEvent).toHaveBeenCalledWith({ key: mockedEventKey }, false);
    });
    test('07 - Escape when not showing the dropdown will not call onDropDownEvent', () => {
        const onDropDownEvent = jest.fn();
        const wrapper = shallow(<InputDropDownDrawer
            inputValue={''}
            onDropDownEvent={onDropDownEvent}
            onSelectOption={(option: { toString: () => string }) => { }}
            showDropDown={false}
            suggestOptions={animals}
        />);

        const mockedEventKey = 'Escape';
        wrapper.find('.input-drop-down-drawer-container').simulate('keyDown', {
            key: mockedEventKey
        });

        expect(wrapper).toMatchSnapshot();
        expect(onDropDownEvent).not.toHaveBeenCalled();
    });
    test('08 - Change the input will call onValueChange and change selectedOption to 0', () => {
        const onValueChange = jest.fn();
        const wrapper = shallow(<InputDropDownDrawer
            inputValue={''}
            onValueChange={onValueChange}
            onDropDownEvent={(event, show: boolean) => { }}
            onSelectOption={(option: { toString: () => string }) => { }}
            showDropDown={true}
            suggestOptions={animals}
        />);

        wrapper.setState({ selectedOption: 5 });

        const mockedNewValue = 'S';
        wrapper.find('.input-drop-down-drawer-input').simulate('change', {
            target: { value: mockedNewValue }
        });

        expect(wrapper).toMatchSnapshot();
        expect(onValueChange).toHaveBeenCalledWith({ target: { value: mockedNewValue } });
        expect(wrapper.state().selectedOption).toBe(0);
    });
    test('09 - Click in the input will call onDropDownEvent as showSelectIcon is true', () => {
        const onDropDownEvent = jest.fn();
        const wrapper = shallow(<InputDropDownDrawer
            inputValue={''}
            onDropDownEvent={onDropDownEvent}
            onSelectOption={(option: { toString: () => string }) => { }}
            showDropDown={false}
            showSelectIcon={true}
            suggestOptions={animals}
        />);

        wrapper.find('.input-drop-down-drawer-input-wrapper').simulate('click');
        expect(wrapper).toMatchSnapshot();
        expect(onDropDownEvent).toHaveBeenCalledWith('CLICK', true);
    });
});
