jest.mock('@boldpenguin/sdk-utility', () => {
    return Object.assign({ __esModule: true }, jest.requireActual('@boldpenguin/sdk-utility'));
});
import { LoadingStates } from "@boldpenguin/sdk-types";
import * as utils from "@boldpenguin/sdk-utility";
import { newSpecPage } from "@stencil/core/testing";
import { BpSdkVehicleYears } from "../bp-sdk-vehicle-years/bp-sdk-vehicle-years";
import { BpSdkVehicleYearsContainer } from "./bp-sdk-vehicle-years-container";
const fakeStore = {
    config: {
        env: 'testEnv',
        uri: 'https://test.local',
    },
    auth: {
        token: 'testToken',
    },
    viewState: {
        vehicleOptions: {
            selection: {
                testId: {
                    yearId: 2018,
                    makeId: '53',
                    modelId: '436357',
                    configurationId: '1440364',
                },
            },
            years: {
                testId: {},
            },
        },
    },
    status: {
        remote: {
            vehicles: {
                testId: LoadingStates.Loaded,
            },
            years: {
                testId: LoadingStates.Loaded,
            },
        },
    },
};
const setupPage = async (additionalComponents = []) => {
    return await newSpecPage({
        html: '<bp-sdk-vehicle-years-container></bp-sdk-vehicle-years-container>',
        components: [BpSdkVehicleYearsContainer, ...additionalComponents],
    });
};
const setupInstance = (page) => {
    const instance = page.rootInstance;
    instance.yearOptions = { 2018: '2018' };
    instance.selectedVehicle = {
        yearId: 2018,
        makeId: '53',
        modelId: '436357',
        configurationId: '1440364',
    };
    instance.questionGroupId = 'testId';
    instance.storeUnsubscribe = jest.fn();
    return instance;
};
describe('bp-sdk-vehicle-years-container', () => {
    it('renders', async () => {
        const page = await setupPage();
        const instance = setupInstance(page);
        instance.yearOptions = { 2020: '2020' };
        instance.selectedVehicle = { yearId: 2018 };
        instance.questionGroupId = 'testId';
        await page.waitForChanges();
        expect(page.root).toEqualHtml(`<bp-sdk-vehicle-years-container><bp-sdk-vehicle-years answeredbysource="" label="Enter vehicle year" pristine="" selectedyear="2018"></bp-sdk-vehicle-years></bp-sdk-vehicle-years-container>`);
    });
    it('render no selection', async () => {
        const page = await setupPage();
        const instance = setupInstance(page);
        instance.yearOptions = { 2020: '2020' };
        instance.selectedVehicle = undefined;
        instance.questionGroupId = 'testId';
        await page.waitForChanges();
        expect(page.root).toEqualHtml(`<bp-sdk-vehicle-years-container><bp-sdk-vehicle-years answeredbysource="" label="Enter vehicle year" pristine="" ></bp-sdk-vehicle-years></bp-sdk-vehicle-years-container>`);
    });
    it('renders handles no year id', async () => {
        const page = await setupPage();
        const instance = setupInstance(page);
        instance.yearOptions = {
            '2020': 2020,
        };
        instance.selectedVehicle = {};
        instance.questionGroupId = 'testId';
        await page.waitForChanges();
        expect(page.root).toEqualHtml(`<bp-sdk-vehicle-years-container><bp-sdk-vehicle-years answeredbysource="" label="Enter vehicle year" pristine=""></bp-sdk-vehicle-years></bp-sdk-vehicle-years-container>`);
    });
    it('renders year id', async () => {
        const page = await setupPage();
        const instance = page.rootInstance;
        instance.yearOptions = {
            '2020': 2020,
        };
        instance.selectedVehicle = {
            yearId: 2020,
        };
        instance.questionGroupId = 'testId';
        await page.waitForChanges();
        expect(page.root).toEqualHtml(`<bp-sdk-vehicle-years-container><bp-sdk-vehicle-years answeredbysource="" label="Enter vehicle year" pristine="" selectedyear="2020"></bp-sdk-vehicle-years></bp-sdk-vehicle-years-container>`);
    });
    it('renders with no years', async () => {
        const page = await setupPage();
        await page.waitForChanges();
        expect(page.root).toEqualHtml(`<bp-sdk-vehicle-years-container></bp-sdk-vehicle-years-container>`);
    });
    it('renders external component if defined', async () => {
        const whenDefinedMock = jest.spyOn(customElements, 'whenDefined').mockResolvedValueOnce({});
        const page = await setupPage();
        const element = page.root.querySelector('bp-sdk-external-vehicle-years-container');
        expect(element).toBeTruthy();
        whenDefinedMock.mockRestore();
    });
    describe('onMakeDirty', () => {
        it('should ignore unchanged touched state', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.touched = false;
            instance.pristine = true;
            instance.onMakeDirty();
            expect(instance.touched).toBeTruthy();
            expect(instance.pristine).toBeFalsy();
        });
    });
    describe('componentDidLoad', () => {
        it('makes expected calls', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            jest.spyOn(instance, 'loadFocusEvents').mockImplementation(() => { });
            instance.componentDidLoad();
            expect(instance.loadFocusEvents).toBeCalledTimes(1);
        });
    });
    describe('disconnectedCallback', () => {
        it('makes expected calls', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            jest.spyOn(instance, 'unloadFocusEvents').mockImplementation(() => { });
            instance.disconnectedCallback();
            expect(instance.unloadFocusEvents).toBeCalledTimes(1);
        });
    });
    describe('onUseExternalChange', () => {
        it('makes expected calls if true', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            jest.spyOn(instance, 'unloadFocusEvents').mockImplementation(() => { });
            instance.onUseExternalChange(true);
            expect(instance.unloadFocusEvents).toBeCalledTimes(0);
        });
        it('makes expected calls if false', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            jest.spyOn(instance, 'unloadFocusEvents').mockImplementation(() => { });
            instance.onUseExternalChange(false);
            expect(instance.unloadFocusEvents).toBeCalledTimes(1);
        });
    });
    describe('loadFocusEvents', () => {
        it('sets expected values', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.useExternal = false;
            jest.spyOn(instance.el, 'addEventListener').mockReturnValue();
            await page.waitForChanges();
            instance.loadFocusEvents();
            expect(instance.el.addEventListener).toBeCalledTimes(1);
            expect(instance.el.addEventListener).toBeCalledWith('focusout', instance.onFocusOut);
        });
        it('handles truthy useExternal', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.useExternal = true;
            jest.spyOn(instance.el, 'addEventListener').mockReturnValue();
            await page.waitForChanges();
            instance.loadFocusEvents();
            expect(instance.el.addEventListener).toBeCalledTimes(0);
        });
    });
    describe('unloadFocusEvents', () => {
        it('sets expected values', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            jest.spyOn(instance.el, 'removeEventListener').mockImplementation(() => { });
            await page.waitForChanges();
            instance.unloadFocusEvents();
            expect(instance.el.removeEventListener).toBeCalledTimes(1);
            expect(instance.el.removeEventListener).toBeCalledWith('focusout', instance.onFocusOut);
        });
    });
    describe('onValueUpdate', () => {
        it('sets expected values', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.pristine = true;
            instance.onValueUpdate({ detail: [''] });
            expect(instance.pristine).toBeFalsy();
            expect(instance.value).toEqual('');
        });
        it('handles null', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.pristine = true;
            instance.onValueUpdate({ detail: null });
            expect(instance.pristine).toBeFalsy();
        });
        it('handles truthy useExternal', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.useExternal = true;
            instance.pristine = true;
            instance.onValueUpdate({ detail: [''] });
            expect(instance.pristine).toBeTruthy();
        });
        it('emits event if no errors', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            jest.spyOn(instance.ymmcUpdate, 'emit').mockReturnValue(null);
            instance.onValueUpdate({ detail: [''] });
            expect(instance.ymmcUpdate.emit).toHaveBeenCalledWith({ type: 'year', value: '' });
        });
        it('does not emit event if there are errors', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.errors = ['required'];
            jest.spyOn(instance, 'updateErrors').mockReturnValue(null);
            jest.spyOn(instance.ymmcUpdate, 'emit').mockReturnValue(null);
            instance.onValueUpdate({ detail: [''] });
            expect(instance.ymmcUpdate.emit).not.toHaveBeenCalled();
        });
    });
    describe('onFocusOut', () => {
        it('sets expected values', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.touched = false;
            instance.onFocusOut();
            expect(instance.touched).toBeTruthy();
        });
    });
    describe('updateErrors', () => {
        it('returns required if error determined', async () => {
            jest.spyOn(utils, 'hasRequiredError').mockReturnValue(true);
            const page = await setupPage();
            const instance = setupInstance(page);
            await page.waitForChanges();
            instance.updateErrors(false, false, '');
            expect(instance.errors).toEqual(['required']);
        });
        it('otherwise empty state', async () => {
            jest.spyOn(utils, 'hasRequiredError').mockReturnValue(false);
            const page = await setupPage();
            const instance = setupInstance(page);
            await page.waitForChanges();
            instance.updateErrors(false, false, '');
            expect(instance.errors).toEqual([]);
        });
    });
    describe('convertYearsToChoices', () => {
        it('converts years to IChoice array', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const years = { '2020': 2020, '2019': 2019 };
            expect(instance.convertYearsToChoices(years)).toEqual([
                { id: '2020', value: '2020' },
                { id: '2019', value: '2019' },
            ]);
        });
        it('sorts in descending order', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const years = { '1981': 1981, '2020': 2020, '1995': 1995, '2019': 2019 };
            expect(instance.convertYearsToChoices(years)).toEqual([
                { id: '2020', value: '2020' },
                { id: '2019', value: '2019' },
                { id: '1995', value: '1995' },
                { id: '1981', value: '1981' },
            ]);
        });
        it('returns empty array if there are no years', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            expect(instance.convertYearsToChoices({})).toEqual([]);
        });
    });
    describe('mapStateToProps', () => {
        it('returns vehicleOptions', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const result = instance.mapStateToProps(fakeStore);
            expect(result.yearOptions).toEqual(fakeStore.viewState.vehicleOptions.years.testId);
            expect(result.selectedVehicle).toEqual(fakeStore.viewState.vehicleOptions.selection.testId);
        });
    });
    describe('handleSubscriptions', () => {
        it('calls unsubscribe if subscribed', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const unsubscribe = jest.fn();
            instance.storeUnsubscribe = unsubscribe;
            instance.handleSubscriptions();
            expect(unsubscribe).toHaveBeenCalled();
        });
        it('overwrites an existing subscribe function', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const unsubscribe = jest.fn();
            instance.storeUnsubscribe = unsubscribe;
            instance.handleSubscriptions();
            expect(instance.storeUnsubscribe).not.toEqual(unsubscribe);
            expect(instance.storeUnsubscribe).toBeDefined();
        });
        it('subscribes if not subscribed', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.storeUnsubscribe = null;
            instance.handleSubscriptions();
            expect(instance.storeUnsubscribe).not.toBeNull();
        });
        it('subscriptions resubscribes if previous subscription exists', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const unsubscribe = jest.fn();
            instance.storeUnsubscribe = unsubscribe;
            instance.handleSubscriptions();
            expect(unsubscribe).toHaveBeenCalledTimes(1);
            expect(instance.storeUnsubscribe).not.toBe(unsubscribe);
        });
    });
    describe('connectedCallback', () => {
        it('makes expected call if root available', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.handleSubscriptions = jest.fn();
            jest.spyOn(instance.el, 'querySelector').mockImplementationOnce(() => ({
                componentOnReady: () => Promise.resolve(true),
            }));
            instance.connectedCallback();
            await page.waitForChanges();
            expect(instance.handleSubscriptions).toBeCalledTimes(1);
        });
    });
    describe('internal state', () => {
        it('passes along code', async () => {
            const page = await setupPage([BpSdkVehicleYears]);
            const instance = setupInstance(page);
            instance.code = 'oldCode';
            await page.waitForChanges();
            const ele = page.root.querySelector('bp-sdk-dynamic-input');
            expect(ele).toEqualAttribute('code', 'oldCode');
        });
    });
    describe('onFilterUpdate', () => {
        it('sets filter prop with detail', async () => {
            const page = await setupPage([BpSdkVehicleYears]);
            const instance = setupInstance(page);
            const detail = { id: 'id', value: 'value' };
            instance.filter = '';
            instance.onFilterUpdate({ detail });
            expect(instance.filter).toEqual(detail.value);
        });
        it('handles null detail', async () => {
            const page = await setupPage([BpSdkVehicleYears]);
            const instance = setupInstance(page);
            const detail = undefined;
            instance.filter = 'some old value';
            instance.onFilterUpdate({ detail });
            expect(instance.filter).toEqual('');
        });
    });
    describe('onYearsChange', () => {
        it('handles calls fetchYears on null data', async () => {
            const page = await setupPage([BpSdkVehicleYears]);
            const instance = setupInstance(page);
            const spy = jest.spyOn(instance, 'fetchYears').mockImplementation(() => jest.fn());
            instance.yearOptions = undefined;
            expect(spy).toHaveBeenCalled();
        });
    });
});
