import { shallowMount } from '@vue/test-utils';
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import buttonMain from '@/ux-components/button-main/button-main.vue';
import { buttonVariants } from '@/constants/component-variants';
import buttonSizes from '@/constants/button-sizes';

/** @ignore */
function setupMocks(mountOptionsMockData = {}) {
    const defaultMountOptions = { route: { query: { issPage: 'page-name' } } };
    const baseMountOptions = getMountOptions(Object.assign(defaultMountOptions, mountOptionsMockData));
    const allMountOptions = Object.assign(defaultMountOptions, baseMountOptions);

    return allMountOptions;
}

describe('buttonMain.vue', () => {
    describe.each([...Object.keys(buttonVariants)])('Button Variants', (variant) => {
        test(`Should return btn-${variant} class`, () => {
            // Act
            const wrapper = shallowMount(
                buttonMain,
                setupMocks({
                    propsData: {
                        variant
                    }
                })
            );

            // Assert
            const button = wrapper.find('button');

            // Expect
            expect(button.attributes('class')).toContain(`btn-${variant}`);
        });
    });

    describe.each([...Object.keys(buttonVariants)])('Button Outline Variants', (variant) => {
        test(`Should return btn-outline-${variant} class`, () => {
            // Act
            const wrapper = shallowMount(
                buttonMain,
                setupMocks({
                    propsData: {
                        variant,
                        isOutline: true
                    }
                })
            );

            // Assert
            const button = wrapper.find('button');

            // Expect
            expect(button.attributes('class')).toContain(`btn-outline-${variant}`);
        });
    });

    describe.each([...Object.keys(buttonSizes)])('Button Sizes', (size) => {
        test(`Should return btn-${size} class`, () => {
            // Act
            const wrapper = shallowMount(
                buttonMain,
                setupMocks({
                    propsData: {
                        size
                    }
                })
            );

            // Assert
            const button = wrapper.find('button');

            // Expect
            expect(button.attributes('class')).toContain(`btn-${size}`);
        });
    });

    it('Should return button text', async () => {
        // Act
        const buttonText = 'Test Text';
        const wrapper = shallowMount(
            buttonMain,
            setupMocks({
                propsData: {
                    buttonText
                }
            })
        );

        // Assert
        const button = wrapper.find('button');

        // Expect
        expect(button.text()).toContain(buttonText);
    });

    it('Should return disabled state', async () => {
        // Act
        const wrapper = shallowMount(
            buttonMain,
            setupMocks({
                propsData: {
                    isDisabled: true
                }
            })
        );

        // Assert
        const button = wrapper.find('button');

        // Expect
        expect(button.attributes()['aria-disabled']).toEqual('true');
    });

    it('Should emit click-event', async () => {
        // Act
        const wrapper = shallowMount(
            buttonMain,
            setupMocks({
                propsData: {
                    isDisabled: false
                }
            })
        );

        // Assert
        const button = wrapper.find('button');
        await button.trigger('click');

        // Expect
        expect(wrapper.emitted('click-event').length).toBe(1);
    });

    it('Should not emit click-event when disabled', async () => {
        // Act
        const wrapper = shallowMount(
            buttonMain,
            setupMocks({
                propsData: {
                    isDisabled: true
                }
            })
        );

        // Assert
        const button = wrapper.find('button');
        await button.trigger('click');

        // Expect
        expect(wrapper.emitted('click-event')).toBeUndefined();
    });

    it('Should emit GA event when clicked', async () => {
        // Act
        const wrapper = shallowMount(
            buttonMain,
            setupMocks({
                propsData: {
                    pushToGA: true
                }
            })
        );

        const spy = jest.spyOn(wrapper.vm, 'pushEventToGA');

        // Assert

        const button = wrapper.find('button');
        await button.trigger('click');

        // Expect
        expect(spy).toHaveBeenCalled();
    });

    it('Should not emit GA event when clicked', async () => {
        // Act
        const wrapper = shallowMount(
            buttonMain,
            setupMocks({
                propsData: {
                    pushToGA: false
                }
            })
        );

        const spy = jest.spyOn(wrapper.vm, 'pushEventToGA');

        // Assert
        const button = wrapper.find('button');
        await button.trigger('click');

        // Expect
        expect(spy).not.toHaveBeenCalled();
    });
});
