import { shallowMount } from '@vue/test-utils';
import FormSelectionControl from '../FormSelectionControl.vue';

describe('FormSelectionControl', () => {
    let attrs;
    let propsData;

    beforeEach(() => {
        attrs = {
            disabled: null,
            id: 'uniqueId1'
        };

        propsData = {
            inputType: 'checkbox',
            value: 'testValue'
        };
    });

    it('should be defined', () => {
        const wrapper = shallowMount(FormSelectionControl, { attrs });
        expect(wrapper.exists()).toBe(true);
    });

    describe('template ::', () => {
        describe('value ::', () => {
            it('should be set using the `value` prop', () => {
                // Arrange & Act
                const wrapper = shallowMount(FormSelectionControl, { propsData, attrs });

                // Assert
                expect(wrapper.find('input').element.value).toBe(propsData.value);
            });
        });

        describe('form-label ::', () => {
            it('should pass labelDescription from $attrs as prop to <form-label>', () => {
                // Arrange & Act
                const expected = 'My label desc';
                const wrapper = shallowMount(FormSelectionControl, { propsData, attrs: { ...attrs, labelDescription: expected } });

                // Assert
                expect(wrapper.find('[data-test-id="selection-control-form-label"]').attributes('labeldescription')).toBe(expected);
            });
        });
    });

    describe('props ::', () => {
        describe('inputType ::', () => {
            it.each([
                [false, 'text'],
                [true, 'checkbox'],
                [true, 'radio']
            ])('should return %s when value is %s', (expected, inputType) => {
                // Arrange
                const { validator } = FormSelectionControl.props.inputType;

                // Act & Assert
                expect(validator(inputType)).toBe(expected);
            });
        });
    });

    describe('computed ::', () => {
        describe('testId ::', () => {
            describe('`attributes.name` is provided ::', () => {
                it('should return an object using the attribute name', async () => {
                    // Arrange
                    propsData.attributes = {
                        name: 'testCheckbox'
                    };

                    const wrapper = shallowMount(FormSelectionControl, { propsData, attrs });

                    // Act
                    const result = await wrapper.vm.testId;

                    // Assert
                    expect(result).toMatchSnapshot();
                });
            });

            describe('`attributes.name` is not provided ::', () => {
                it('should return a generic object without using the attribute name', async () => {
                    // Arrange
                    propsData.attributes = {
                        name: null
                    };

                    const wrapper = shallowMount(FormSelectionControl, { propsData, attrs });

                    // Act
                    const result = await wrapper.vm.testId;

                    // Assert
                    expect(result).toMatchSnapshot();
                });
            });
        });

        describe('showRequiredIndicator ::', () => {
            it.each([
                [true, 'required', true],
                [true, '', true],
                [true, true, true],
                [false, undefined, true],
                [false, false, true],
                [false, 'required', false],
                [false, '', false],
                [false, true, false],
                [false, undefined, false],
                [false, false, false]
            ])('should return %s if required attribute is %s and isVisuallyRequired is %s', (expected, required, isVisuallyRequired) => {
                // Arrange & Act
                const wrapper = shallowMount(FormSelectionControl, {
                    attrs,
                    propsData: {
                        ...propsData,
                        attributes: {
                            required
                        },
                        isVisuallyRequired
                    }
                });

                // Assert
                expect(wrapper.vm.showRequiredIndicator).toBe(expected);
            });
        });
    });

    describe('methods ::', () => {
        describe('updateSelectionControl ::', () => {
            it('should emit `update` when changed', async () => {
                // Arrange
                const wrapper = shallowMount(FormSelectionControl, { propsData, attrs });

                const event = {
                    target: {
                        value: 'anotherTestValue'
                    }
                };

                // Act
                await wrapper.vm.updateSelectionControl(event);

                // Assert
                expect(wrapper.emitted('update').length).toBe(1);
            });
        });
    });
});
