import { getPartnerEngineConfig } from "@boldpenguin/sdk-redux";
import { AnalyticsTrackingEventName, BpEnvironmentName, LoadingStates, QuestionFieldType, } from "@boldpenguin/sdk-types";
import { mockDocument, newSpecPage } from "@stencil/core/testing";
import { updateAnswerValue, getErrors, isValidAnswer, hasAnswerChanged, getQuestionGroupsWithParentQuestionIdAsKey, getQuestionGroupWithParentQuestionAnswerIdAsKey, hasAnswer, } from "@boldpenguin/sdk-utility";
jest.mock('@boldpenguin/sdk-utility', () => ({
    updateAnswerValue,
    getErrors,
    isValidAnswer,
    hasAnswerChanged,
    hasAnswer,
    focusErrors: jest.fn(),
    markElementDirty: jest.fn(),
    getQuestionGroupsWithParentQuestionIdAsKey,
    getQuestionGroupWithParentQuestionAnswerIdAsKey,
}));
import { focusErrors } from "@boldpenguin/sdk-utility";
import { BpSdkQuestionSetContainer } from "./bp-sdk-question-set-container";
import { h } from "@stencil/core";
let fakeStore;
const setupPage = async (overwriteProps) => {
    return await newSpecPage({
        components: [BpSdkQuestionSetContainer],
        template: () => {
            const props = Object.assign({ questionSets: fakeStore.application.questionSets, config: getPartnerEngineConfig(fakeStore), answersResourceState: fakeStore.status.remote.answers.state, applicationFormResourceState: fakeStore.status.remote.application.form, questionPoolResourceState: fakeStore.status.remote.questionPools.state, questionSetResourceState: fakeStore.status.remote.questionSets.state, storeUnsubscribe: jest.fn() }, overwriteProps);
            return h("bp-sdk-question-set-container", Object.assign({}, props));
        },
    });
};
describe('BpSdkQuestionSetContainer', () => {
    beforeEach(() => {
        fakeStore = {
            application: {
                form: {
                    locked: false,
                },
                questionSets: {
                    list: [],
                    active: '',
                },
            },
            status: {
                remote: {
                    application: {
                        form: LoadingStates.Loaded,
                    },
                    answers: {
                        state: LoadingStates.Loaded,
                    },
                    questionPools: {
                        state: LoadingStates.Loaded,
                    },
                    questionSets: {
                        state: LoadingStates.Loaded,
                    },
                },
            },
            queues: {
                answers: [],
            },
            config: {
                uri: 'http://test.local',
                env: BpEnvironmentName.Alpha,
                options: { enableUserApplicationGuard: true },
            },
            auth: {
                token: 'test_token',
            },
        };
    });
    describe('disconnectedCallback', () => {
        it('should make expected calls', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            await page.waitForChanges();
            instance.storeUnsubscribe = jest.fn();
            instance.disconnectedCallback();
            expect(instance.storeUnsubscribe).toHaveBeenCalledTimes(1);
        });
    });
    describe('mapStateToProps', () => {
        it('returns an object with the correct keys', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            const result = instance.mapStateToProps(fakeStore);
            expect(result).toHaveProperty('questionSets');
            expect(result).toHaveProperty('config');
            expect(result).toHaveProperty('locked');
            expect(result).toHaveProperty('queue');
            expect(result).toHaveProperty('answersResourceState');
            expect(result).toHaveProperty('applicationFormResourceState');
            expect(result).toHaveProperty('questionPoolResourceState');
            expect(result).toHaveProperty('questionSetResourceState');
            expect(result).toHaveProperty('enableUserApplicationGuard');
        });
    });
    describe('calculateResourcesReady', () => {
        it('should return false if no resources', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            expect(instance.calculateResourcesReady(null)).toBe(false);
        });
        it('should return false if undefined resources', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            expect(instance.calculateResourcesReady(undefined)).toBe(false);
        });
        it('should return false when form is loading', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.isReady = true;
            instance.applicationFormResourceState = LoadingStates.Loading;
            expect(instance.calculateResourcesReady({
                answers: LoadingStates.Loaded,
                applicationForm: LoadingStates.Loading,
                questionPools: LoadingStates.Loaded,
                questionSets: LoadingStates.Loaded,
            })).toBe(false);
        });
        it('should return false when question pool is loading', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.isReady = true;
            instance.questionPoolResourceState = LoadingStates.Loading;
            expect(instance.calculateResourcesReady({
                answers: LoadingStates.Loaded,
                applicationForm: LoadingStates.Loaded,
                questionPools: LoadingStates.Loading,
                questionSets: LoadingStates.Loaded,
            })).toBe(false);
        });
        it('should return false when question sets are loading', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.isReady = true;
            expect(instance.calculateResourcesReady({
                answers: LoadingStates.Loaded,
                applicationForm: LoadingStates.Loaded,
                questionPools: LoadingStates.Loaded,
                questionSets: LoadingStates.Loading,
            })).toBe(false);
        });
        it('should return false when answers are loading', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.isReady = true;
            instance.answersResourceState = LoadingStates.Loading;
            expect(instance.calculateResourcesReady({
                answers: LoadingStates.Loading,
                applicationForm: LoadingStates.Loaded,
                questionPools: LoadingStates.Loaded,
                questionSets: LoadingStates.Loaded,
            })).toBe(false);
        });
        it('should return true', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.isReady = false;
            await page.waitForChanges();
            expect(instance.calculateResourcesReady({
                answers: LoadingStates.Loaded,
                applicationForm: LoadingStates.Loaded,
                questionPools: LoadingStates.Loaded,
                questionSets: LoadingStates.Loaded,
            })).toBe(true);
        });
    });
    describe('handleSaveQuestionSet', () => {
        beforeEach(() => {
            jest.useFakeTimers({ legacyFakeTimers: true });
        });
        it('should make expected calls', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            jest.spyOn(instance, 'removeActiveAnswerId').mockImplementation(jest.fn());
            instance.answersResourceState = LoadingStates.Loaded;
            instance.questionSetResourceState = LoadingStates.Loaded;
            jest.spyOn(instance, 'saveQuestionSet').mockImplementation(jest.fn());
            jest.spyOn(instance, 'updateErrors').mockImplementation(jest.fn());
            instance.questionSets;
            const set = {
                answers: [],
                question_set_id: 'abc',
                question_set: {
                    code: 'xyz',
                },
            };
            const bpAnalyticsTrackSpy = jest.spyOn(instance.bpAnalyticsTrack, 'emit');
            instance.handleSaveQuestionSet(set);
            expect(instance.saveQuestionSet).toHaveBeenCalledTimes(1);
            expect(instance.saveQuestionSet).toHaveBeenCalledWith({
                config: instance.config,
                appFormQuestionSet: set,
                navigationDirection: 'forward',
            });
            expect(bpAnalyticsTrackSpy).toHaveBeenCalledTimes(1);
            expect(bpAnalyticsTrackSpy).toHaveBeenCalledWith({
                eventName: AnalyticsTrackingEventName.QuestionSetSaved,
                eventPayload: { applicationFormQuestionSetId: set.id, questionSetId: set.question_set_id, questionSetCode: set.question_set.code },
            });
            expect(instance.updateErrors).toBeCalledTimes(0);
        });
        it('should ignore expected answers', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            jest.spyOn(instance, 'removeActiveAnswerId').mockImplementation(jest.fn());
            instance.answersResourceState = LoadingStates.Loaded;
            instance.questionSetResourceState = LoadingStates.Loaded;
            jest.spyOn(instance, 'saveQuestionSet').mockImplementation(jest.fn());
            jest.spyOn(instance, 'updateErrors').mockImplementation(jest.fn());
            instance.questionSets;
            const set = {
                answers: [
                    {
                        active: false,
                    },
                    {
                        active: true,
                        is_completed: true,
                    },
                ],
                question_set: {},
            };
            const element = {
                scrollIntoView: jest.fn(),
                getAttributeNode: () => null,
            };
            mockDocument();
            jest.spyOn(document, 'querySelector').mockReturnValue(element);
            instance.handleSaveQuestionSet(set);
            jest.advanceTimersByTime(100);
            expect(instance.saveQuestionSet).toHaveBeenCalledTimes(1);
            expect(instance.saveQuestionSet).toHaveBeenCalledWith({
                config: instance.config,
                appFormQuestionSet: set,
                navigationDirection: 'forward',
            });
            expect(instance.updateErrors).toBeCalledTimes(0);
            expect(element.scrollIntoView).toHaveBeenCalledTimes(0);
        });
        it('handle errors as expected', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            mockDocument();
            instance.answersResourceState = LoadingStates.Loaded;
            instance.questionSetResourceState = LoadingStates.Loaded;
            jest.spyOn(instance, 'saveQuestionSet').mockImplementation(jest.fn());
            jest.spyOn(instance, 'updateErrors').mockImplementation(jest.fn());
            instance.questionSets;
            const set = {
                answers: [
                    {
                        active: true,
                        is_completed: false,
                        required: true,
                        value: null,
                        question: {
                            field_type: 'text',
                            required: true,
                        },
                    },
                ],
            };
            jest.spyOn(document, 'querySelectorAll').mockImplementation(() => ['any', 'el']);
            jest.spyOn(document, 'querySelector').mockReturnValue(null);
            const bpAnalyticsTrackSpy = jest.spyOn(instance.bpAnalyticsTrack, 'emit');
            instance.handleSaveQuestionSet(set);
            jest.advanceTimersByTime(100);
            expect(instance.updateErrors).toBeCalledTimes(1);
            expect(instance.updateErrors).toHaveBeenCalledWith({
                answer: set.answers[0],
                errors: ['required'],
            });
            expect(instance.saveQuestionSet).toHaveBeenCalledTimes(0);
            expect(bpAnalyticsTrackSpy).toHaveBeenCalledTimes(0);
        });
        it('scrolls to first error if present', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.answersResourceState = LoadingStates.Loaded;
            instance.questionSetResourceState = LoadingStates.Loaded;
            jest.spyOn(instance, 'saveQuestionSet').mockImplementation(jest.fn());
            jest.spyOn(instance, 'updateErrors').mockImplementation(jest.fn());
            instance.questionSets;
            const set = {
                answers: [
                    {
                        active: true,
                        required: true,
                        value: null,
                        question: {
                            field_type: 'text',
                            required: true,
                        },
                    },
                ],
            };
            const element = {
                parentElement: { scrollIntoView: jest.fn(), getAttributeNode: () => null },
            };
            mockDocument();
            jest.spyOn(document, 'querySelectorAll').mockReturnValue([]);
            jest.spyOn(document, 'querySelector').mockReturnValue(element);
            instance.handleSaveQuestionSet(set);
            jest.advanceTimersByTime(100);
            expect(instance.saveQuestionSet).toHaveBeenCalledTimes(0);
            expect(instance.updateErrors).toBeCalledTimes(1);
            expect(instance.updateErrors).toHaveBeenCalledWith({
                answer: set.answers[0],
                errors: ['required'],
            });
            expect(focusErrors).toHaveBeenCalled();
        });
    });
    describe('handleSaveAnswer', () => {
        describe('single', () => {
            it('does nothing if useExternal', async () => {
                const page = await setupPage();
                const instance = page.rootInstance;
                instance.useExternal = true;
                jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                const event = new CustomEvent('saveAnswer', {
                    detail: {
                        new_value: ['some value'],
                        answer: {
                            is_completed: false,
                            question: {
                                field_type: 'dropdown',
                                multiple: false,
                            },
                        },
                    },
                });
                instance.handleSaveAnswer(event);
                expect(instance.pushAnswer).toBeCalledTimes(0);
            });
        });
        describe(`should not call pushAnswer if answer's value has not changed`, () => {
            describe('coverage_type single', () => {
                it('should only call pushAnswer if has changed or is_completed is false', async () => {
                    const page = await setupPage();
                    const instance = page.rootInstance;
                    jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                    const spy = jest.spyOn(instance, 'pushAnswer');
                    instance.questionSets = {
                        pendingActiveAnswerUpdate: undefined,
                    };
                    const eventToUnchangedCoverageType = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: 'same as before',
                            answer: {
                                id: '123',
                                is_completed: true,
                                question: {
                                    field_type: QuestionFieldType.CoverageType,
                                    multiple: false,
                                },
                                choice_id: 'same as before',
                            },
                        },
                    });
                    const eventToChangedCoverageType = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: 'new value',
                            answer: {
                                id: '123',
                                is_completed: true,
                                question: {
                                    field_type: QuestionFieldType.CoverageType,
                                    multiple: false,
                                },
                                choice_id: 'same as before',
                            },
                        },
                    });
                    instance.handleSaveAnswer(eventToUnchangedCoverageType);
                    expect(spy).not.toHaveBeenCalled();
                    instance.handleSaveAnswer(eventToChangedCoverageType);
                    expect(spy).toHaveBeenCalledTimes(1);
                });
                it('should call pushAnswer if a matching pendingAnswerUpdate exists', async () => {
                    const page = await setupPage();
                    const instance = page.rootInstance;
                    instance.pushAnswer = jest.fn();
                    const spy = jest.spyOn(instance, 'pushAnswer');
                    const eventToUnchangedCoverageType = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: 'same as before',
                            answer: {
                                id: '123',
                                is_completed: true,
                                question: {
                                    field_type: QuestionFieldType.CoverageType,
                                    multiple: false,
                                },
                                choice_id: 'same as before',
                            },
                        },
                    });
                    instance.handleSaveAnswer(eventToUnchangedCoverageType);
                    expect(spy).not.toHaveBeenCalled();
                    instance.questionSets = {
                        pendingActiveAnswerUpdate: {
                            id: '123',
                            is_completed: true,
                            question: {
                                field_type: QuestionFieldType.CoverageType,
                                multiple: false,
                            },
                            choice_id: 'not same as before',
                        },
                    };
                    instance.handleSaveAnswer(eventToUnchangedCoverageType);
                    expect(spy).toHaveBeenCalledTimes(1);
                });
            });
            describe('coverage_type multiple', () => {
                it('should only call pushAnswer if has changed or is_completed is false', async () => {
                    const page = await setupPage();
                    const instance = page.rootInstance;
                    jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                    const spy = jest.spyOn(instance, 'pushAnswer');
                    const eventToUnchangedCoverageTypeMultiple = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: ['same as before'],
                            answer: {
                                id: '123',
                                is_completed: true,
                                question: {
                                    field_type: QuestionFieldType.CoverageType,
                                    multiple: true,
                                },
                                choice_ids: ['same as before'],
                            },
                        },
                    });
                    instance.handleSaveAnswer(eventToUnchangedCoverageTypeMultiple);
                    expect(spy).not.toHaveBeenCalled();
                    const eventToChangedCoverageTypeMultiple = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: ['new value'],
                            answer: {
                                id: '123',
                                is_completed: true,
                                question: {
                                    field_type: QuestionFieldType.CoverageType,
                                    multiple: true,
                                },
                                choice_ids: ['same as before'],
                            },
                        },
                    });
                    instance.handleSaveAnswer(eventToChangedCoverageTypeMultiple);
                    expect(spy).toHaveBeenCalled();
                });
            });
            describe('text', () => {
                it('should only call pushAnswer if answer has changed or is_completed is false', async () => {
                    const page = await setupPage();
                    const instance = page.rootInstance;
                    jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                    const spy = jest.spyOn(instance, 'pushAnswer');
                    const eventToUnchangedText = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: 'same as before',
                            answer: {
                                id: '123',
                                is_completed: true,
                                question: {
                                    field_type: QuestionFieldType.Text,
                                },
                                value: 'same as before',
                            },
                        },
                    });
                    const eventToChangedText = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: 'different answer',
                            answer: {
                                id: '123',
                                is_completed: true,
                                question: {
                                    field_type: QuestionFieldType.Text,
                                },
                                value: 'same as before',
                            },
                        },
                    });
                    instance.handleSaveAnswer(eventToUnchangedText);
                    expect(spy).not.toHaveBeenCalled();
                    instance.handleSaveAnswer(eventToChangedText);
                    expect(spy).toHaveBeenCalled();
                });
            });
        });
        describe('dropdown', () => {
            describe('single', () => {
                it('should make expected calls', async () => {
                    const page = await setupPage();
                    const instance = page.rootInstance;
                    jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                    const event = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: ['some value'],
                            answer: {
                                id: '123',
                                is_completed: false,
                                question: {
                                    field_type: 'dropdown',
                                    multiple: false,
                                },
                            },
                        },
                    });
                    instance.handleSaveAnswer(event);
                    expect(instance.pushAnswer).toBeCalledTimes(1);
                    expect(instance.pushAnswer).toHaveBeenCalledWith(Object.assign(Object.assign({}, event.detail.answer), { choice_id: event.detail.new_value[0] }));
                });
                it('should have fallback', async () => {
                    const page = await setupPage();
                    const instance = page.rootInstance;
                    jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                    const event = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: [''],
                            answer: {
                                id: '123',
                                is_completed: false,
                                question: {
                                    field_type: 'dropdown',
                                    multiple: false,
                                },
                            },
                        },
                    });
                    instance.handleSaveAnswer(event);
                    expect(instance.pushAnswer).toBeCalledTimes(1);
                    expect(instance.pushAnswer).toHaveBeenCalledWith(Object.assign(Object.assign({}, event.detail.answer), { choice_id: null }));
                });
            });
            describe('multiple', () => {
                it('should make expected calls', async () => {
                    const page = await setupPage();
                    const instance = page.rootInstance;
                    jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                    const event = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: ['some value'],
                            answer: {
                                id: '123',
                                is_completed: false,
                                question: {
                                    field_type: 'dropdown',
                                    multiple: true,
                                },
                            },
                        },
                    });
                    instance.handleSaveAnswer(event);
                    expect(instance.pushAnswer).toBeCalledTimes(1);
                    expect(instance.pushAnswer).toHaveBeenCalledWith(Object.assign(Object.assign({}, event.detail.answer), { choice_ids: event.detail.new_value }));
                });
                it('should have fallback', async () => {
                    const page = await setupPage();
                    const instance = page.rootInstance;
                    jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                    const event = new CustomEvent('saveAnswer', {
                        detail: {
                            new_value: '',
                            answer: {
                                id: '123',
                                is_completed: false,
                                choice_ids: [''],
                                question: {
                                    field_type: 'dropdown',
                                    multiple: true,
                                },
                            },
                        },
                    });
                    instance.handleSaveAnswer(event);
                    expect(instance.pushAnswer).toBeCalledTimes(1);
                    expect(instance.pushAnswer).toHaveBeenCalledWith(Object.assign(Object.assign({}, event.detail.answer), { choice_ids: [] }));
                });
            });
        });
        describe('radio', () => {
            it('should make expected calls', async () => {
                const page = await setupPage();
                const instance = page.rootInstance;
                jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                const event = new CustomEvent('saveAnswer', {
                    detail: {
                        new_value: 'some value',
                        answer: {
                            id: '123',
                            is_completed: false,
                            question: {
                                field_type: 'radio',
                            },
                        },
                    },
                });
                instance.handleSaveAnswer(event);
                expect(instance.pushAnswer).toBeCalledTimes(1);
                expect(instance.pushAnswer).toHaveBeenCalledWith(Object.assign(Object.assign({}, event.detail.answer), { value: null, choice_id: event.detail.new_value }));
            });
            it('should have fallback', async () => {
                const page = await setupPage();
                const instance = page.rootInstance;
                jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                const event = new CustomEvent('saveAnswer', {
                    detail: {
                        new_value: '',
                        answer: {
                            id: '123',
                            is_completed: false,
                            question: {
                                field_type: 'radio',
                            },
                        },
                    },
                });
                instance.handleSaveAnswer(event);
                expect(instance.pushAnswer).toBeCalledTimes(1);
                expect(instance.pushAnswer).toHaveBeenCalledWith(Object.assign(Object.assign({}, event.detail.answer), { value: null, choice_id: null }));
            });
        });
        describe('text', () => {
            it('should make expected calls', async () => {
                const page = await setupPage();
                const instance = page.rootInstance;
                jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                const event = new CustomEvent('saveAnswer', {
                    detail: {
                        new_value: 'some value',
                        answer: {
                            id: '123',
                            is_completed: false,
                            question: {
                                field_type: 'text',
                            },
                        },
                    },
                });
                instance.handleSaveAnswer(event);
                expect(instance.pushAnswer).toBeCalledTimes(1);
                expect(instance.pushAnswer).toHaveBeenCalledWith(Object.assign(Object.assign({}, event.detail.answer), { value: event.detail.new_value }));
            });
            it('should have fallback', async () => {
                const page = await setupPage();
                const instance = page.rootInstance;
                jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                const event = new CustomEvent('saveAnswer', {
                    detail: {
                        new_value: '',
                        answer: {
                            id: '123',
                            is_completed: false,
                            question: {
                                field_type: 'text',
                            },
                        },
                    },
                });
                instance.handleSaveAnswer(event);
                expect(instance.pushAnswer).toBeCalledTimes(1);
                expect(instance.pushAnswer).toHaveBeenCalledWith(Object.assign(Object.assign({}, event.detail.answer), { value: null }));
            });
        });
        describe('Re-test incomplete questions even with no value change', () => {
            it('should make call when answer if answer is incomplete', async () => {
                const page = await setupPage();
                const instance = page.rootInstance;
                jest.spyOn(instance, 'pushAnswer').mockImplementation(jest.fn());
                const event = new CustomEvent('saveAnswer', {
                    detail: {
                        new_value: 'same as before',
                        answer: {
                            id: '123',
                            is_completed: false,
                            question: {
                                field_type: 'text',
                            },
                        },
                    },
                });
                instance.handleSaveAnswer(event);
                expect(instance.pushAnswer).toBeCalledTimes(1);
                expect(instance.pushAnswer).toHaveBeenCalledWith(Object.assign(Object.assign({}, event.detail.answer), { value: event.detail.new_value }));
            });
        });
    });
    describe('onRemoveActiveAnswerRequest', () => {
        it('makes expected calls', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            jest.spyOn(instance, 'removeActiveAnswerId').mockImplementation(jest.fn());
            instance.onRemoveActiveAnswerRequest();
            expect(instance.removeActiveAnswerId).toBeCalledTimes(1);
        });
    });
    describe('onUpdateActiveAnswerRequest', () => {
        it('makes expected calls', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.questionSets = {
                list: [
                    {
                        answers: [
                            { id: '0', question: { id: '0' } },
                            { id: '1', question: { id: '1' } },
                            { id: '2', question: { id: '2' } },
                        ],
                    },
                ],
            };
            jest.spyOn(instance, 'updateActiveAnswerId').mockImplementation(jest.fn());
            instance.onUpdateActiveAnswerRequest({ detail: '1' });
            expect(instance.updateActiveAnswerId).toBeCalledTimes(1);
            expect(instance.updateActiveAnswerId).toBeCalledWith('1');
        });
        it('does nothing if no match', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.questionSets = {
                list: [
                    {
                        answers: [
                            { id: '0', question: { id: '0' } },
                            { id: '2', question: { id: '2' } },
                        ],
                    },
                ],
            };
            jest.spyOn(instance, 'updateActiveAnswerId').mockImplementation(jest.fn());
            instance.onUpdateActiveAnswerRequest({ detail: '1' });
            expect(instance.updateActiveAnswerId).toBeCalledTimes(0);
        });
    });
    describe('render', () => {
        it('vanilla', async () => {
            const page = await setupPage({
                questionSets: {
                    active: '1',
                    list: [
                        {
                            question_set_id: '1',
                            answers: [],
                            question_set: { code: 'basic_information' },
                        },
                        { answers: [], question_set_id: '2' },
                    ],
                },
            });
            await page.waitForChanges();
            expect(page.rootInstance).toBeTruthy();
            expect(page.root.querySelectorAll('bp-sdk-question-set').length).toBe(1);
            expect(page.root.querySelectorAll('bp-sdk-question-set-header').length).toBe(1);
        });
        it('loading', async () => {
            const page = await setupPage();
            page.rootInstance.isFirstRun = true;
            page.rootInstance.isLoadingApplication = true;
            await page.waitForChanges();
            expect(page.rootInstance).toBeTruthy();
            expect(page.root.querySelectorAll('bp-sdk-application-load').length).toBe(1);
        });
        it('handles broken question set', async () => {
            const page = await setupPage({
                questionSets: {
                    active: '1',
                    list: [
                        {
                            question_set_id: '1',
                            answers: [],
                        },
                        { answers: [], question_set_id: '2' },
                    ],
                },
            });
            await page.waitForChanges();
            expect(page.rootInstance).toBeTruthy();
            expect(page.root.querySelectorAll('bp-sdk-question-set').length).toBe(1);
            expect(page.root.querySelectorAll('bp-sdk-question-set-header').length).toBe(1);
        });
        it('active queue', async () => {
            const page = await setupPage({
                questionSets: {
                    active: '1',
                    list: [
                        {
                            question_set_id: '1',
                            answers: [],
                            question_set: { code: 'basic_information' },
                        },
                        { answers: [], question_set_id: '2' },
                    ],
                },
                queue: [],
            });
            await page.waitForChanges();
            expect(page.rootInstance).toBeTruthy();
            expect(page.root.querySelectorAll('bp-sdk-question-set').length).toBe(1);
            expect(page.root.querySelectorAll('bp-sdk-question-set-header').length).toBe(1);
        });
        it('handle no question set', async () => {
            const page = await setupPage({
                questionSets: {
                    active: '1',
                    list: [
                        { question_set_id: '1', answers: [], question_set: {} },
                        { answers: [], question_set_id: '2' },
                    ],
                },
            });
            await page.waitForChanges();
            expect(page.rootInstance).toBeTruthy();
            expect(page.root.querySelectorAll('bp-sdk-question-set').length).toBe(1);
            expect(page.root.querySelectorAll('bp-sdk-question-set-header').length).toBe(1);
        });
        it('handle no code', async () => {
            const page = await setupPage({
                questionSets: {
                    active: '1',
                    list: [
                        { question_set_id: '1', answers: [], question_set: {} },
                        { answers: [], question_set_id: '2' },
                    ],
                },
            });
            await page.waitForChanges();
            expect(page.rootInstance).toBeTruthy();
            expect(page.root.querySelectorAll('bp-sdk-question-set').length).toBe(1);
            expect(page.root.querySelectorAll('bp-sdk-question-set-header').length).toBe(1);
        });
        it('should render empty set', async () => {
            const page = await setupPage({
                questionSets: {
                    active: '1',
                    list: [
                        {
                            answers: [],
                            is_blank: true,
                            question_set_id: '1',
                            question_set: {
                                name: 'Coterie',
                            },
                        },
                    ],
                },
                queue: [],
            });
            await page.waitForChanges();
            expect(page.rootInstance).toBeTruthy();
            expect(page.root.querySelector('bp-sdk-question-set-empty')).toBeTruthy();
            expect(page.root.querySelectorAll('bp-sdk-question-set-header').length).toBe(1);
        });
        it('can render external', async () => {
            jest.spyOn(customElements, 'whenDefined').mockReturnValueOnce(Promise.resolve({}));
            const page = await setupPage();
            await page.waitForChanges();
            expect(page.rootInstance).toBeTruthy();
            expect(page.root.querySelector('bp-sdk-question-set')).toBeFalsy();
        });
    });
    describe('disconnectedCallback', () => {
        it('should make expected calls', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.storeUnsubscribe = jest.fn();
            instance.disconnectedCallback();
            expect(instance.storeUnsubscribe).toBeCalledTimes(1);
        });
        it('handles null storeUnsubscribe', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.storeUnsubscribe = undefined;
            instance.disconnectedCallback();
            expect(instance.storeUnsubscribe).toBeUndefined();
        });
    });
    describe('handleSubscriptions', () => {
        it('subscribes if not subscribed', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            instance.storeUnsubscribe = null;
            instance.handleSubscriptions();
            expect(instance.storeUnsubscribe).not.toBeNull();
        });
        it('resubscribes to mapStateToProps if already has storeUnsubscribe', async () => {
            const page = await setupPage();
            const instance = page.rootInstance;
            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 = page.rootInstance;
            instance.handleSubscriptions = jest.fn();
            jest.spyOn(instance.el, 'querySelector').mockImplementationOnce(() => ({
                componentOnReady: () => Promise.resolve(true),
            }));
            instance.connectedCallback();
            expect(instance.handleSubscriptions).toBeCalledTimes(1);
            await page.waitForChanges();
            expect(instance.handleSubscriptions).toBeCalledTimes(2);
        });
    });
    describe('updateIsLocked', () => {
        let instance;
        beforeEach(async () => {
            const page = await setupPage();
            instance = page.rootInstance;
        });
        it('should be locked whenever locked is true', () => {
            instance.updateIsLocked(true, false, false, true);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, true, false, true);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, false, true, true);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, true, true, false);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, true, true, true);
            expect(instance.isLocked).toBe(true);
        });
        it('should not be locked whenever isOwner is false', () => {
            instance.updateIsLocked(true, false, false, true);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, false, false, true);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, false, true, true);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, false, true, true);
            expect(instance.isLocked).toBe(true);
        });
        it('should be locked whenever hasPermission is false', () => {
            instance.updateIsLocked(true, false, false, true);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, false, false, true);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, false, false, true);
            expect(instance.isLocked).toBe(true);
            instance.updateIsLocked(true, false, false, true);
            expect(instance.isLocked).toBe(true);
        });
        it('should not check hasPermission or isOwner if enableUserApplicationGuard is false', () => {
            instance.updateIsLocked(false, false, false, false);
            expect(instance.isLocked).toBe(false);
        });
        it('should not be locked when not locked, is owner and has permission', () => {
            instance.updateIsLocked(true, true, true, true);
            expect(instance.isLocked).toBe(true);
        });
    });
    describe('canSave', () => {
        let instance;
        beforeEach(async () => {
            const page = await setupPage();
            instance = page.rootInstance;
        });
        it('should be true if there is nothing in the queue and no pending processes', () => {
            instance.pendingProcesses = [];
            instance.onQueueChange({});
            expect(instance.canSave).toBeTruthy();
        });
        it('should be false if there is something in the queue and no pending processes', () => {
            instance.pendingProcesses = [];
            instance.onQueueChange([{}]);
            expect(instance.canSave).toBeFalsy();
        });
        it('should be false if there is nothing in the queue but there are pending processes on active QS', () => {
            instance.questionSets.active = '123';
            instance.pendingProcesses = [{ question_set_id: '123' }];
            instance.onQueueChange();
            expect(instance.canSave).toBeFalsy();
        });
        it('should be true if there is nothing in the queue and there are no pending processes on active QS', () => {
            instance.questionSets.active = '123';
            instance.pendingProcesses = [{ question_set_id: '1234' }];
            instance.onQueueChange();
            expect(instance.canSave).toBeTruthy();
        });
    });
});
