import React from 'react';
import { render } from '@testing-library/react';
import { formatMessage } from '@theorchard/suite-i18n';
import PageView from '../pageView';

interface Props {
    error: boolean;
    loading: boolean;
    hasData: boolean;
    showContentWhenEmpty: boolean;
}

describe('PageView', () => {
    const CONTENT = 'some content';
    const ERROR = 'some error';
    const error = new Error(ERROR);

    const renderView = (props: Partial<Props> = {}) =>
        render(
            <PageView
                loading={props.loading || false}
                hasData={props.hasData || false}
                error={props.error ? error : undefined}
                showContentWhenEmpty={props.showContentWhenEmpty || false}
            >
                <div>{CONTENT}</div>
            </PageView>
        );

    const showsContent = (props: Partial<Props>) => {
        test('shows content', () => {
            const { getByText } = renderView(props);
            expect(getByText(CONTENT)).toBeVisible();
        });
    };

    const hidesContent = (props: Partial<Props>) => {
        test('hides content', () => {
            const { queryByText } = renderView(props);
            expect(queryByText(CONTENT)).toBeNull();
        });
    };

    const showsLoadingIndicator = (props: Partial<Props>) => {
        test('shows loading indicator', () => {
            const { container } = renderView(props);
            expect(container.getElementsByClassName('LoadingPageIndicator').item(0)).toBeVisible();
        });
    };

    const hidesLoadingIndicator = (props: Partial<Props>) => {
        test('does not show loading indicator', () => {
            const { container } = renderView(props);
            expect(container.getElementsByClassName('LoadingIndicator').item(0)).toBeNull();
        });
    };

    const showsErrorMessage = (props: Partial<Props>) => {
        test('renders error message', () => {
            const { container, getByText } = renderView(props);
            expect(container.getElementsByClassName('ErrorMessage').item(0)).toBeVisible();
            expect(getByText(formatMessage('error_generic_title'))).toBeVisible();
        });
    };

    const hidesErrorMessage = (props: Partial<Props>) => {
        test('does not render error message', () => {
            const { container, queryByText } = renderView(props);
            expect(container.getElementsByClassName('ErrorMessage').item(0)).toBeNull();
            expect(queryByText(formatMessage('error_generic_title'))).toBeNull();
        });
    };

    test('renders element with "PageView" class', () => {
        const { getByTestId } = renderView();
        const element = getByTestId('PageView');
        expect(element).toBeVisible();
        expect(element).toHaveClass('PageView');
    });

    describe.each([
        [
            { hasData: true, loading: false, error: false },
            [showsContent, hidesLoadingIndicator, hidesErrorMessage],
        ],
        [
            { hasData: true, loading: true, error: false },
            [showsContent, hidesLoadingIndicator, hidesErrorMessage],
        ],
        [
            { hasData: true, loading: true, error: true },
            [showsContent, hidesLoadingIndicator, showsErrorMessage],
        ],
        [
            { hasData: true, loading: false, error: true },
            [showsContent, hidesLoadingIndicator, showsErrorMessage],
        ],
        [
            { hasData: false, loading: false, error: false },
            [hidesContent, hidesLoadingIndicator, hidesErrorMessage],
        ],
        [
            { hasData: false, loading: true, error: false },
            [hidesContent, showsLoadingIndicator, hidesErrorMessage],
        ],
        [
            { hasData: false, loading: true, error: true },
            [hidesContent, hidesLoadingIndicator, showsErrorMessage],
        ],
        [
            { hasData: false, loading: false, error: true },
            [hidesContent, hidesLoadingIndicator, showsErrorMessage],
        ],
        [
            {
                hasData: false,
                loading: false,
                error: false,
                showContentWhenEmpty: true,
            },
            [showsContent, hidesLoadingIndicator, hidesErrorMessage],
        ],
    ])('when %o', (props, tests) => {
        tests.forEach((t) => t(props));
    });
});
