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

describe('<Dropdown.View />', function() {
    const dropdownItems = [ {
        value: 1,
        title: 'oh beans 1'
    }, {
        value: 2,
        title: 'oh beans 2'
    }, {
        value: 3,
        title: 'oh beans 3'
    }, {
        value: 4,
        title: 'oh beans 4'
    }, {
        value: 5,
        title: 'oh beans 5'
    } ];

    it('should dry initialize', function() {
        const wrapper = shallow(
            <Dropdown.View />);

        expect(wrapper.hasClass('dropdown')).to.be.true;
        expect(wrapper.find('.header').text()).to.equal('Choose');
        expect(wrapper.find('.options')).to.have.length(1);
        expect(wrapper.find('.options').find('.option')).to.have.length(0);
    });

    it('should toggle', function() {
        const wrapper = shallow(
            <Dropdown.View
                items={ dropdownItems } />);

        wrapper.find('.header').simulate('click');

        expect(wrapper.hasClass('active')).to.be.true;

        wrapper.find('.header').simulate('click');

        expect(wrapper.hasClass('active')).to.be.false;
    });

    it('should have an adder', function() {
        const spy = sinon.spy(),
            wrapper = mount(
                <Dropdown.View
                    items={ dropdownItems }
                    onAdd={ { title: 'Add', callback: spy } }/>);

        wrapper.find('.header').simulate('click');

        expect(wrapper.find('.option'))
            .to.have.length(dropdownItems.length + 1);
        expect(wrapper.find('.option').last().text()).to.equal('Add');

        wrapper.find('.option').last().simulate('click');

        expect(wrapper.hasClass('active')).to.be.false;
        expect(spy.callCount).to.equal(1);
    });

    it('should dry add', function() {
        const wrapper = mount(
            <Dropdown.View
                items={ dropdownItems }
                onAdd />);

        wrapper.find('.header').simulate('click');

        expect(wrapper.find('.option').last().text()).to.equal('Add New');
    });

    it('should show some options', function() {
        const wrapper = mount(<Dropdown.View items={ dropdownItems } />);

        expect(wrapper.find('.option')).to.have.length(dropdownItems.length);
    });

    it('should allow clicking on options', function() {
        const spy = sinon.spy(),
            wrapper = mount(
                <Dropdown.View
                    items={ dropdownItems }
                    onSelect={ spy } />);

        wrapper.find('.option').at(3).simulate('click');
        expect(spy.callCount).to.equal(1);
        expect(spy.getCall(0).args[0].title).to.equal('oh beans 4');
    });

    it('should select on start', function() {
        const wrapper = mount(
            <Dropdown.View
                items={ dropdownItems }
                value={ 3 } />);

        expect(wrapper.find('.option').at(2).hasClass('active'))
            .to.be.true;
    });

    it('should be disabled if empty', function() {
        const wrapper = shallow(<Dropdown.View />);

        expect(wrapper.hasClass('disabled')).to.be.true;

        wrapper.find('.header').simulate('click');

        expect(wrapper.find('.option')).to.have.length(0);
    });

    it('should not be disabled if empty with adder', function() {
        const shallowed = shallow(<Dropdown.View onAdd />),
            mounted = mount(<Dropdown.View onAdd />);

        expect(shallowed.hasClass('disabled')).to.be.false;

        mounted.find('.header').simulate('click');

        expect(mounted.find('.option')).to.have.length(1);
    });

    it('should be disabled if I say so', function() {
        const wrapper = shallow(
            <Dropdown.View
                items={ dropdownItems }
                disabled />);

        expect(wrapper.hasClass('disabled')).to.be.true;

        wrapper.find('.header').simulate('click');

        expect(wrapper.find('.option')).to.have.length(0);
    });

    it('should become disabled if no items anymore', function() {
        const wrapper = shallow(
            <Dropdown.View
                items={ dropdownItems } />);

        expect(wrapper.hasClass('disabled')).to.be.false;

        wrapper.setProps({ items: [] });

        expect(wrapper.hasClass('disabled')).to.be.true;
    });

    it('should acknowledge an error through props', function() {
        const wrapper = shallow(
            <Dropdown.View
                error="test error message"
                items={ dropdownItems } />);

        expect(wrapper.hasClass('has-error')).to.be.true;
    });

    it('should not show error if disabled', function() {
        const wrapper = mount(
            <Dropdown.View
                error="test error msg"
                disabled
                items={ dropdownItems } />);

        expect(wrapper.find('.error-tooltip')).to.have.lengthOf(0);
    });

    it('should allow native dropdown', function() {
        const shallowed = shallow(
            <Dropdown.View
                native
                items={ dropdownItems } />),
            mounted = mount(
                <Dropdown.View
                    native
                    items={ dropdownItems } />);

        expect(shallowed.hasClass('native')).to.be.true;
        expect(mounted.find('select')).to.have.length(1);
        // plus 1 because there is a "default" option for placeholder
        expect(mounted.find('option')).to.have.length(dropdownItems.length + 1);
    });

    it('even native should call onAdd callback', function() {
        const spy = sinon.spy(),
            wrapper = mount(
                <Dropdown.View
                    native
                    onAdd={ { title: 'Add', callback: spy } }
                    items={ dropdownItems } />);

        expect(wrapper.find('option').last().text()).to.equal('Add');
        wrapper.find('select').simulate('change', {
            target: {
                value: undefined
            }
        });
        expect(spy.callCount).to.equal(1);
    });

    it('native should allow selecting options', function() {
        const wrapper = mount(
            <Dropdown.View
                native
                items={ dropdownItems } />);

        wrapper.find('select').simulate('change', {
            target: {
                value: `${dropdownItems[2].value}`
            }
        });

        expect(wrapper.state('at')).to.equal(3);
        expect(wrapper.state('value')).to.equal(dropdownItems[2].value);
    });
});
