import * as Sentry from '@sentry/browser';
import { render } from '@testing-library/react';
import { disableConsoleErrors } from 'lib/test/utils';
import React from 'react';
import ErrorBoundary from '../errorBoundary';

describe('<ErrorBoundary>', () => {
    disableConsoleErrors();

    test('renders children', () => {
        const output = 'im behaving';
        const Child = () => <div>{output}</div>;
        const wrapper = render(<ErrorBoundary><Child /></ErrorBoundary>);

        expect(wrapper.getByText(output)).toBeDefined();
    });

    describe('on error', () => {
        const output = 'im misbehaving';
        const error = new Error(output);
        const Child = () => { throw error; };

        const scope = { setExtras: jest.fn() } as unknown as Sentry.Scope;
        const eventId = '1234';

        jest.spyOn(Sentry, 'withScope').mockImplementation((callback) => callback(scope));
        const captureException = jest.spyOn(Sentry, 'captureException').mockReturnValue(eventId);

        beforeEach(() => {
            captureException.mockClear();
        });

        test('renders error message', () => {
            const wrapper = render(<ErrorBoundary><Child /></ErrorBoundary>);
            const errorMessage = wrapper.getByText(output);

            expect(errorMessage).toBeVisible();
        });

        test('sends error to Sentry', () => {
            render(<ErrorBoundary><Child /></ErrorBoundary>);

            expect(scope.setExtras).toHaveBeenCalledWith({
                componentStack: '\n    in Child\n    in ErrorBoundary'
            });
            expect(Sentry.captureException).toHaveBeenCalledWith(error);
        });
    });
});
