import { BpEnvironmentName } from "@boldpenguin/sdk-types";
import { newSpecPage } from "@stencil/core/testing";
import { BpSdkSendToExchangeContainer } from "./bp-sdk-send-to-exchange-container";
let fakeStore;
const setupPage = async () => {
    return await newSpecPage({
        html: '<bp-sdk-send-to-exchange-container></bp-sdk-send-to-exchange-container>',
        components: [BpSdkSendToExchangeContainer],
    });
};
const setupInstance = (page, overrideStore) => {
    if (overrideStore) {
        fakeStore = overrideStore;
    }
    else {
        fakeStore = {
            application: {
                form: {
                    id: 'testId',
                },
                choices: {},
                questionSets: {
                    list: [],
                },
            },
            config: { uri: 'https://test.local/', env: BpEnvironmentName.Alpha },
            auth: { token: 'testToken', expiresAt: 0 },
        };
    }
    const instance = page.rootInstance;
    instance.storeUnsubscribe = jest.fn();
    jest.spyOn(instance, 'createQuestionSet').mockImplementationOnce(jest.fn());
    instance.canSendToExchange = true;
    instance.isCurrentOwner = true;
    return instance;
};
describe('bp-sdk-send-to-exchange-container', () => {
    afterEach(() => {
        jest.resetAllMocks();
    });
    it('renders', async () => {
        const page = await setupPage();
        setupInstance(page);
        await page.waitForChanges();
        const element = page.root.querySelector('bp-sdk-send-to-exchange');
        expect(element).toBeTruthy();
        expect(page.root.querySelector('bp-sdk-external-send-to-exchange-container')).toBeFalsy();
    });
    it('renders nothing when canSendToExchange is false', async () => {
        const page = await setupPage();
        const instance = setupInstance(page);
        instance.canSendToExchange = false;
        await page.waitForChanges();
        const element = page.root.querySelector('bp-sdk-send-to-exchange');
        expect(element).toBeFalsy();
        expect(page.root.querySelector('bp-sdk-external-send-to-exchange-container')).toBeFalsy();
    });
    it('renders nothing when isCurrentOwner is false', async () => {
        const page = await setupPage();
        const instance = setupInstance(page);
        instance.isCurrentOwner = false;
        await page.waitForChanges();
        const element = page.root.querySelector('bp-sdk-send-to-exchange');
        expect(element).toBeFalsy();
        expect(page.root.querySelector('bp-sdk-external-send-to-exchange-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-send-to-exchange-container')).toBeTruthy();
        whenDefinedMock.mockRestore();
    });
    describe('sendToExchange', () => {
        it('should make expected calls', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.sendToExchange();
            expect(instance.createQuestionSet).toBeCalledTimes(1);
            expect(instance.createQuestionSet).toBeCalledWith({
                config: instance.config,
                appFormQuestionSet: {
                    application_form_id: instance.appFormId,
                    question_set: {
                        code: 'send_to_bold_penguin',
                    },
                },
            });
        });
    });
    describe('disconnectedCallback', () => {
        it('should make expected calls', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.disconnectedCallback();
            expect(instance.storeUnsubscribe).toHaveBeenCalledTimes(1);
        });
    });
    describe('mapStateToProps', () => {
        it('returns an object containing all the expected keys', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const result = instance.mapStateToProps(fakeStore);
            expect(result).toHaveProperty('config');
            expect(result).toHaveProperty('appFormId');
            expect(result).toHaveProperty('isCurrentOwner');
            expect(result).toHaveProperty('canSendToExchange');
            expect(result).toHaveProperty('hasSentToExchange');
        });
    });
    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);
        });
    });
});
