import { newSpecPage } from "@stencil/core/testing";
import { BpSdkDynamicInputReduxContainer } from "./bp-sdk-dynamic-input-redux-container";
const defaultStore = {
    application: {
        errors: {},
        questionSets: {
            activeAnswerId: '',
        },
    },
};
const buildStore = (store = defaultStore) => {
    var _a, _b, _c, _d, _e;
    return (Object.assign(Object.assign({}, defaultStore), { application: {
            errors: Object.assign({}, ((_b = (_a = store === null || store === void 0 ? void 0 : store.application) === null || _a === void 0 ? void 0 : _a.errors) !== null && _b !== void 0 ? _b : defaultStore.application.errors)),
            questionSets: {
                activeAnswerId: (_e = (_d = (_c = store === null || store === void 0 ? void 0 : store.application) === null || _c === void 0 ? void 0 : _c.questionSets) === null || _d === void 0 ? void 0 : _d.activeAnswerId) !== null && _e !== void 0 ? _e : defaultStore.application.questionSets.activeAnswerId,
            },
        } }));
};
const setupPage = async () => {
    return await newSpecPage({
        html: '<bp-sdk-dynamic-input-redux-container></bp-sdk-dynamic-input-redux-container>',
        components: [BpSdkDynamicInputReduxContainer],
    });
};
const setupInstance = (page) => {
    const answer = {
        active: true,
        question: {
            id: 'bob',
        },
    };
    const instance = page.rootInstance;
    instance.answer = answer;
    return instance;
};
describe('bp-sdk-dynamic-input-redux-container', () => {
    describe('rendering', () => {
        it('vanilla', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.answer = {
                active: true,
                question: {
                    id: 'bob',
                },
            };
            await page.waitForChanges();
            expect(page.root.querySelector('bp-sdk-dynamic-input-event-container')).toBeTruthy();
            expect(page.root.querySelector('bp-sdk-external-dynamic-input-redux-container')).toBeFalsy();
        });
        it('has fallbacks', async () => {
            const page = await setupPage();
            expect(page.root.querySelector('bp-sdk-dynamic-input-event-container')).toBeTruthy();
            expect(page.root.querySelector('bp-sdk-external-dynamic-input-redux-container')).toBeFalsy();
        });
        it('renders external component if defined', async () => {
            const whenDefinedMock = jest.spyOn(customElements, 'whenDefined').mockResolvedValueOnce({});
            const page = await setupPage();
            await page.waitForChanges();
            expect(page.root.querySelector('bp-sdk-dynamic-input-event-container')).toBeFalsy();
            expect(page.root.querySelector('bp-sdk-external-dynamic-input-redux-container')).toBeTruthy();
            whenDefinedMock.mockRestore();
        });
    });
    describe('handleUpdateActiveAnswerId', () => {
        it('makes expected calls', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            jest.spyOn(instance, 'updateActiveAnswerId').mockImplementation(jest.fn());
            instance.handleUpdateActiveAnswerId('bob');
            expect(instance.updateActiveAnswerId).toHaveBeenCalledTimes(1);
            expect(instance.updateActiveAnswerId).toHaveBeenCalledWith('bob');
        });
    });
    describe('componentWillLoad', () => {
        it('calls onErrorsStateChange', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.onErrorsStateChange = jest.fn();
            instance.componentWillLoad();
            expect(instance.onErrorsStateChange).toHaveBeenCalled();
        });
        it('calls onAnswerChange', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.onAnswerChange = jest.fn();
            instance.componentWillLoad();
            expect(instance.onAnswerChange).toHaveBeenCalled();
        });
    });
    describe('mapStateToProps', () => {
        it('should return an object with the correct keys', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const result = instance.mapStateToProps(buildStore());
            expect(result).toHaveProperty('errorState');
            expect(result).toHaveProperty('activeId');
        });
    });
    describe('getErrors', () => {
        it('should emit errors if isAccumulatorAnswer', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.isAccumulatorAnswer = true;
            const spy = jest.spyOn(instance.errorsUpdate, 'emit');
            instance.errorState = { [instance.answer.id]: ['min'] };
            await page.waitForChanges();
            expect(spy).toHaveBeenCalledWith(['min']);
        });
    });
    describe('disconnectedCallback', () => {
        it('makes expected calls', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.storeUnsubscribe = jest.fn();
            instance.disconnectedCallback();
            expect(instance.storeUnsubscribe).toHaveBeenCalledTimes(1);
        });
    });
    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('subscribes updates mapStateToProps if already has storeUnsubscribe', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const unsubscribe = jest.fn();
            instance.storeUnsubscribe = unsubscribe;
            instance.handleSubscriptions();
            expect(instance.storeUnsubscribe).not.toEqual(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);
        });
    });
});
