import createSelector from '../createSelector';
import {
    hasMultipleVariantsSelected,
    isSelectedAmountsUpdated,
    getDeepestChildIdentifiers,
} from '../../../App/Reducers/Configurator/Selectors';

describe('Utils/Function/createSelector', () => {
    const configurator = {
        configuration: {
            item: {
                identifier: 'demo_hoodie',
                parentItemIdentifier: 'demo_hoodie',
                settings: {
                    visualizationCreator: '2d',
                    visualizationDesigner: '2d',
                },
                title: 'Demo Kaputzenpullover',
                itemGroup: {
                    identifier: 'color',
                    title: 'Farbe',
                    children: [
                        {
                            identifier: 'demo_hoodie_blue_s',
                            title: 'Demo Kaputzenpullover Blau S',
                            children: null,
                            itemGroup: {
                                identifier: 'size',
                                title: 'Größe',
                                children: [
                                    {
                                        identifier: 'demo_hoodie_blue_s',
                                        title: 'Demo Kaputzenpullover Blau S',
                                        children: null,
                                        itemgroupentryIdentifier: 's',
                                        itemgroupentryTitle: 'Größe S',
                                    },
                                    {
                                        identifier: 'demo_hoodie_blue_m',
                                        title: 'Demo Kaputzenpullover Blau M',
                                        children: null,
                                        itemgroupentryIdentifier: 'm',
                                        itemgroupentryTitle: 'Größe M',
                                    },
                                    {
                                        identifier: 'demo_hoodie_blue_l',
                                        title: 'Demo Kaputzenpullover Blau L',
                                        children: null,
                                        itemgroupentryIdentifier: 'l',
                                        itemgroupentryTitle: 'Größe L',
                                    },
                                    {
                                        identifier: 'demo_hoodie_blue_xl',
                                        title: 'Demo Kaputzenpullover Blau XL',
                                        children: null,
                                        itemgroupentryIdentifier: 'xl',
                                        itemgroupentryTitle: 'Größe XL',
                                    },
                                ],
                            },
                            itemgroupentryIdentifier: 'blue',
                            itemgroupentryTitle: 'blau',
                        },
                        {
                            identifier: 'demo_hoodie_green_s',
                            title: 'Demo Kaputzenpullover Grün S',
                            children: null,
                            itemGroup: {
                                identifier: 'size',
                                title: 'Größe',
                                children: [
                                    {
                                        identifier: 'demo_hoodie_green_s',
                                        title: 'Demo Kaputzenpullover Grün S',
                                        children: null,
                                        itemgroupentryIdentifier: 's',
                                        itemgroupentryTitle: 'Größe S',
                                    },
                                    {
                                        identifier: 'demo_hoodie_green_m',
                                        title: 'Demo Kaputzenpullover Grün M',
                                        children: null,
                                        itemgroupentryIdentifier: 'm',
                                        itemgroupentryTitle: 'Größe M',
                                    },
                                    {
                                        identifier: 'demo_hoodie_green_l',
                                        title: 'Demo Kaputzenpullover Grün L',
                                        children: null,
                                        itemgroupentryIdentifier: 'l',
                                        itemgroupentryTitle: 'Größe L',
                                    },
                                    {
                                        identifier: 'demo_hoodie_green_xl',
                                        title: 'Demo Kaputzenpullover Grün XL',
                                        children: null,
                                        itemgroupentryIdentifier: 'xl',
                                        itemgroupentryTitle: 'Größe XL',
                                    },
                                ],
                            },
                            itemgroupentryIdentifier: 'green',
                            itemgroupentryTitle: 'grün',
                        },
                    ],
                },
                itemclassifications: [],
            },
            customdata: {
                selectedAmounts: { demo_hoodie_blue_s: 1, demo_hoodie_green_m: 2 },
            },
        },
        selectedAmountsUpdated: true,
    };
    test('throws error if gets a non-function argument', () => {
        expect(() => createSelector(null)).toThrowError();
    });
    test('throws error if gets a non-function dependency argument', () => {
        expect(() => createSelector(() => {}, 0)).toThrowError();
    });
    test('calls the selector function with the dependency result', () => {
        const itemIdentifier = jest.fn(item => item.identifier);
        const getItem = jest.fn(obj => obj.item);
        const selector = createSelector(getItem, itemIdentifier);
        expect(selector({ item: { identifier: 'foo' } })).toEqual('foo');
        expect(selector({ item: { identifier: 'bar' } })).toEqual('bar');
        expect(selector({ item: { identifier: 'baz' } })).toEqual('baz');
        expect(itemIdentifier).toBeCalledTimes(3);
        expect(getItem).toBeCalledTimes(3);
    });
    test('do not call the selector function nor the dependency function if the input is unchanged', () => {
        const itemIdentifier = jest.fn();
        const getItem = jest.fn(obj => obj.item);
        const selector = createSelector(getItem, itemIdentifier);
        const inputRef = { item: { identifier: 'foo' } };
        selector(inputRef);
        selector(inputRef);
        selector(inputRef);
        expect(itemIdentifier).toBeCalledTimes(1);
        expect(getItem).toBeCalledTimes(1);
    });
    test('do not call the selector function if the dependency is unchanged', () => {
        const itemIdentifier = jest.fn();
        const getItem = jest.fn(obj => obj.item);
        const selector = createSelector(getItem, itemIdentifier);
        const item = { identifier: 'foo' };
        const inputRef = { item };
        const inputRef2 = { item };
        const inputRef3 = { item };
        selector(inputRef);
        selector(inputRef2);
        selector(inputRef3);
        expect(itemIdentifier).toBeCalledTimes(1);
        expect(getItem).toBeCalledTimes(3);
    });
    test('hasMultipleVariantsSelected returns true if multiple variants selected', () => {
        expect(hasMultipleVariantsSelected(configurator)).toBe(true);
    });
    test('isSelectedAmountUpdated return correct state value', () => {
        expect(isSelectedAmountsUpdated(configurator)).toEqual(true);
    });
    test('getDeepestChildIdentifiers return correct values', () => {
        expect(getDeepestChildIdentifiers(configurator.configuration.item.itemGroup.children[0])).toEqual({
            l: 'demo_hoodie_blue_l',
            m: 'demo_hoodie_blue_m',
            s: 'demo_hoodie_blue_s',
            xl: 'demo_hoodie_blue_xl',
        });
    });
});
