import { newSpecPage } from "@stencil/core/testing";
import { BpSdkQuestionPoolContainer } from "./bp-sdk-question-pool-container";
const fakeStore = {
    auth: {
        token: 'some token',
    },
    config: {
        env: 'dev',
        uri: 'http://someuri.js',
    },
    application: {
        form: {
            id: 'some id',
        },
        questionSets: {
            list: [],
        },
    },
};
const setupPage = async () => {
    return await newSpecPage({
        html: '<bp-sdk-question-pool-container></bp-sdk-question-pool-container>',
        components: [BpSdkQuestionPoolContainer],
    });
};
const setupInstance = (page) => {
    const instance = page.rootInstance;
    jest.spyOn(instance, 'addQuestionPool').mockImplementation(jest.fn());
    instance.storeUnsubscribe = jest.fn();
    return instance;
};
describe('bp-sdk-question-pool-container', () => {
    it('renders', async () => {
        const page = await setupPage();
        await page.waitForChanges();
        const element = page.root.querySelector('bp-sdk-add-item-container');
        expect(element).toBeTruthy();
        expect(page.root.querySelector('bp-sdk-external-question-pool-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-external-question-pool-container')).toBeTruthy();
        whenDefinedMock.mockRestore();
    });
    describe('onParentQuestionPoolSelected', () => {
        it('should call addQuestionPool', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            await page.waitForChanges();
            instance.onParentQuestionPoolSelected({ detail: 'some id' });
            expect(instance.addQuestionPool).toHaveBeenCalledWith(expect.objectContaining({ selected_answer_pool_id: 'some id' }));
        });
    });
    describe('handleAddItem', () => {
        it('should make expected calls', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.handleAddItem();
            expect(instance.addQuestionPool).toBeCalledTimes(1);
            expect(instance.addQuestionPool).toBeCalledWith({
                config: instance.config,
                application_id: instance.applicationId,
                question_pool_id: instance.guid,
            });
        });
        it('should set selectParentPoolQuestion', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.parentQuestionPoolId = 'some id';
            instance.selectParentPoolQuestion = false;
            instance.parentQuestionPoolReferenceId = '123';
            instance.handleAddItem();
            expect(instance.selectParentPoolQuestion).toBeTruthy();
        });
        it('should not dispatch addQuestionPool if parentQuestionPoolReferenceId is defined', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.parentQuestionPoolId = 'some id';
            instance.selectParentPoolQuestion = false;
            instance.parentQuestionPoolReferenceId = '123';
            instance.handleAddItem();
            instance.handleAddItem();
            expect(instance.addQuestionPool).not.toHaveBeenCalled();
        });
    });
    describe('selectedAnswerPoolId', () => {
        it('should addQuestionPool if selected', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.parentQuestionPoolId = 'some id';
            instance.selectParentPoolQuestion = true;
            instance.parentQuestionPoolReferenceId = '123';
            instance.onParentQuestionPoolSelected(new CustomEvent('selectedAnswerPoolId', { detail: '123' }));
            expect(instance.addQuestionPool).toHaveBeenCalled();
        });
    });
    describe('getParentAnswers', () => {
        it('should return answers filtered by reference id', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const answers = [
                {
                    question: {
                        id: 'some id 1',
                        reference_id: 'some id 1',
                        value: 'some value 1',
                    },
                },
                {
                    question: {
                        id: 'some id 2',
                        reference_id: 'some id 2',
                        value: 'some value 2',
                    },
                },
            ];
            instance.currentQuestionSet = {
                answers: answers,
            };
            instance.parentQuestionPoolReferenceId = 'some id 1';
            const result = instance.getParentAnswers();
            expect(result).toEqual([answers[0]]);
        });
    });
    describe('mapStateToProps', () => {
        it('returns expected props', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const result = instance.mapStateToProps(fakeStore);
            expect(result.config).toEqual(Object.assign(Object.assign({}, fakeStore.auth), fakeStore.config));
            expect(result.applicationId).toEqual(fakeStore.application.form.id);
        });
    });
    describe('disconnectedCallback', () => {
        it('should make expected calls', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.disconnectedCallback();
            expect(instance.storeUnsubscribe).toBeCalledTimes(1);
        });
        it('handles null storeUnsubscribe', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.storeUnsubscribe = undefined;
            instance.disconnectedCallback();
            expect(instance.storeUnsubscribe).toBeUndefined();
        });
    });
    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);
        });
    });
});
