import React from 'react';
import { shallow, mount } from 'enzyme';
import { MultiSelect } from 'web-foundation';

describe('<MultiSelect />', function() {
    const multiSelectOptions = [ {
        value: 0,
        title: 'Squirtle'
    }, {
        value: 1,
        title: 'Charmander'
    }, {
        value: 2,
        title: 'Bulbasaur'
    } ];

    it('should initialize properly', function() {
        const wrapper = shallow(<MultiSelect options={ multiSelectOptions } />);

        expect(wrapper.hasClass('multi-select')).to.be.true;
        expect(wrapper.find('MultiSelectOption'))
            .to.have.length(multiSelectOptions.length);
    });

    it('should accept additional class names', function() {
        const wrapper = shallow(
            <MultiSelect options={ multiSelectOptions }
                className="foo" />
        );

        expect(wrapper.hasClass('multi-select')).to.be.true;
        expect(wrapper.hasClass('foo')).to.be.true;
    });

    it('should invoke my selection callback on selection', function() {
        const spy = sinon.spy(),
            wrapper = mount(
                <MultiSelect options={ multiSelectOptions }
                    onSelection={ spy } />
            ),
            selectedOptionIdx = 0;

        wrapper.find('MultiSelectOption').at(selectedOptionIdx)
            .simulate('click');

        expect(spy.calledOnce).to.be.true;
        expect([ ...spy.getCall(0).args[0] ])
            .to.contain(multiSelectOptions[selectedOptionIdx].value);
    });

    it('should also unselect an option', function() {
        const spy = sinon.spy(),
            selectedOptionIdx = 0,
            wrapper = mount(
                <MultiSelect options={ multiSelectOptions }
                    selected={ [ multiSelectOptions[selectedOptionIdx].value ] }
                    onSelection={ spy } />
            );

        // unselect
        wrapper.find('MultiSelectOption').at(selectedOptionIdx)
            .simulate('click');

        expect(spy.calledOnce).to.be.true;
        expect([ ...spy.getCall(0).args[0] ])
            .to.not.contain(multiSelectOptions[selectedOptionIdx].value);
    });

    it('should allow selecting multiple options', function() {
        const spy = sinon.spy(),
            selectedOptionIndices = [ 0, 1 ],
            wrapper = mount(
                <MultiSelect options={ multiSelectOptions }
                    selected={
                        selectedOptionIndices.map((idx) =>
                            multiSelectOptions[idx].value
                        )
                    }
                    onSelection={ spy } />
            );

        expect(wrapper.find('.option.selected'))
            .to.have.length(selectedOptionIndices.length);

        wrapper.find('MultiSelectOption')
            .at(selectedOptionIndices[0])
            .simulate('click');

        expect(spy.calledOnce).to.be.true;
        expect([ ...spy.getCall(0).args[0] ])
            .to.not.contain(multiSelectOptions[selectedOptionIndices[0]].value);
        expect([ ...spy.getCall(0).args[0] ])
            .to.contain(multiSelectOptions[selectedOptionIndices[1]].value);
    });
});

