import { ReduxAsyncError } from "@boldpenguin/sdk-types";
import { newSpecPage } from "@stencil/core/testing";
import { BpSdkErrorEventContainer } from "./bp-sdk-error-event-container";
const fakeStore = {
    config: {
        debug: true,
    },
};
const setupPage = async () => {
    return await newSpecPage({
        html: '<bp-sdk-error-event-container></bp-sdk-error-event-container>',
        components: [BpSdkErrorEventContainer],
    });
};
const setupInstance = (page) => {
    const instance = page.rootInstance;
    instance.storeUnsubscribe = jest.fn();
    instance.sdkError = {
        emit: jest.fn(),
    };
    return instance;
};
describe('bp-sdk-error-event-container', () => {
    afterEach(() => {
        jest.resetAllMocks();
    });
    describe('handleError', () => {
        describe('SDK Error', () => {
            let mockErrorEvent;
            beforeEach(() => {
                mockErrorEvent = {
                    error: new ReduxAsyncError('Fake Redux Error'),
                };
            });
            it('should call .emit', async () => {
                const page = await setupPage();
                const instance = setupInstance(page);
                expect(instance.sdkError.emit).not.toHaveBeenCalled();
                instance.handleError(mockErrorEvent);
                expect(instance.sdkError.emit).toHaveBeenCalledWith({ error: mockErrorEvent.error });
            });
            it('should call console.error when debug flag is true', async () => {
                const page = await setupPage();
                const instance = setupInstance(page);
                instance.isDebug = true;
                const consoleSpy = jest.spyOn(global.console, 'error').mockImplementation();
                expect(consoleSpy).not.toHaveBeenCalled();
                instance.handleError(mockErrorEvent);
                expect(consoleSpy).toHaveBeenCalledWith(mockErrorEvent.error);
            });
            it('should not call console.error when isDebug is false', async () => {
                const page = await setupPage();
                const instance = setupInstance(page);
                instance.isDebug = false;
                const consoleSpy = jest.spyOn(global.console, 'error').mockImplementation();
                expect(consoleSpy).not.toHaveBeenCalled();
                instance.handleError(mockErrorEvent);
                expect(consoleSpy).not.toHaveBeenCalled();
            });
            it('should call the errorHandler function when one is passed as a prop', async () => {
                const page = await setupPage();
                const instance = setupInstance(page);
                instance.errorHandler = jest.fn();
                expect(instance.errorHandler).not.toHaveBeenCalled();
                instance.handleError(mockErrorEvent);
                expect(instance.errorHandler).toHaveBeenCalledWith(mockErrorEvent.error);
            });
        });
        describe('Non-SDK Error', () => {
            let mockErrorEvent;
            beforeEach(() => {
                mockErrorEvent = {
                    error: new Error('Non-SDK Error'),
                };
            });
            it('should not call the errorHandler function', async () => {
                const page = await setupPage();
                const instance = setupInstance(page);
                instance.errorHandler = jest.fn();
                expect(instance.errorHandler).not.toHaveBeenCalled();
                instance.handleError(mockErrorEvent);
                expect(instance.errorHandler).not.toHaveBeenCalled();
            });
            it('should not call console.error', async () => {
                const page = await setupPage();
                const instance = setupInstance(page);
                instance.isDebug = true;
                const consoleSpy = jest.spyOn(global.console, 'error').mockImplementation();
                expect(consoleSpy).not.toHaveBeenCalled();
                instance.handleError(mockErrorEvent);
                expect(consoleSpy).not.toHaveBeenCalled();
            });
            it('should not call .emit', async () => {
                const page = await setupPage();
                const instance = setupInstance(page);
                expect(instance.sdkError.emit).not.toHaveBeenCalled();
                instance.handleError(mockErrorEvent);
                expect(instance.sdkError.emit).not.toHaveBeenCalled();
            });
        });
    });
    describe('componentWillLoad', () => {
        it('should call addEventListener', async () => {
            const page = await setupPage();
            page.win.addEventListener = jest.fn();
            const instance = setupInstance(page);
            instance.componentWillLoad();
            await page.waitForChanges();
            expect(page.win.addEventListener).toHaveBeenCalledWith('error', instance.handleError);
        });
    });
    describe('disconnectedCallback', () => {
        it('should unsubscribe from the redux store', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            instance.disconnectedCallback();
            expect(instance.storeUnsubscribe).toHaveBeenCalledTimes(1);
        });
    });
    describe('mapStateToProps', () => {
        it('returns the isDebug flag from the store', async () => {
            const page = await setupPage();
            const instance = setupInstance(page);
            const result = instance.mapStateToProps(fakeStore);
            expect(result.isDebug).toEqual(fakeStore.config.debug);
        });
    });
});
