import React from 'react';
import { render } from '@testing-library/react';
import { ErrorBoundary, muteConsole } from 'lib/testUtils';
import { I18nProvider } from '../context';
import { WithI18n } from '../types';
import { useI18n } from '../useI18n';

describe('useI18n', () => {
    const term1 = 'hi';
    const term2 = 'there';

    const MyComponent: WithI18n & React.FC = () => {
        const { t, tx } = useI18n();
        return (
            <div>
                <span>{t('term1')}</span>
                <span>{tx('term2')}</span>
            </div>
        );
    };

    muteConsole();

    test('uses messages in context', () => {
        const { getByText } = render(
            <I18nProvider messages={{ term1, term2 }}>
                <MyComponent />
            </I18nProvider>
        );
        expect(getByText(term1)).toBeInTheDocument();
        expect(getByText(term2)).toBeInTheDocument();
    });

    test('throws if no context', () => {
        const { getByTestId } = render(<MyComponent />, {
            wrapper: ({ children }) => <ErrorBoundary>{children}</ErrorBoundary>,
        });
        expect(getByTestId('error')).toHaveTextContent('I18n messages not available in context.');
    });

    describe('with key', () => {
        const key = 'my-key';
        const MyComponentWithKey = () => {
            const { t } = useI18n(key);
            return <div>{t('term1')}</div>;
        };

        test('throws if no matching key', () => {
            const { getByTestId } = render(
                <I18nProvider messages={{ term1 }}>
                    <MyComponentWithKey />
                </I18nProvider>,
                {
                    wrapper: ({ children }) => <ErrorBoundary>{children}</ErrorBoundary>,
                }
            );

            expect(getByTestId('error')).toHaveTextContent(
                `No I18n messages by the key "${key}". Loaded keys: "term1".`
            );
        });

        test('throws if invalid key', () => {
            const { getByTestId } = render(
                <I18nProvider messages={{ [key]: 'not an object' }}>
                    <MyComponentWithKey />
                </I18nProvider>,
                {
                    wrapper: ({ children }) => <ErrorBoundary>{children}</ErrorBoundary>,
                }
            );

            expect(getByTestId('error')).toHaveTextContent(
                `No valid I18n messages by the key "${key}". The key resolves to a string and not an object.`
            );
        });
    });
});
