import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import { createIdentity } from 'lib/test-utils/identity-factory';
import { MemoryRouter } from 'react-router-dom';
import IdentityContext from 'src/context';
import HeaderGlobalSearch, {
    CLASSNAME_GLOBAL_SEARCH,
    CLASSNAME_CLOSE_OVERLAY,
    CLASSNAME_ICON,
    CLASSNAME_CLOSE_BTN,
} from '../header-global-search';

describe('<HeaderGlobalSearch>', () => {
    const renderComponent = (identity: ReturnType<typeof createIdentity>) =>
        render(
            <IdentityContext.Provider
                value={{ identity, hasAuthentication: () => false }}
            >
                <MemoryRouter>
                    <HeaderGlobalSearch />
                </MemoryRouter>
            </IdentityContext.Provider>
        );

    const expectSearchVisible = (container: HTMLElement, value: boolean) => {
        if (value) {
            expect(
                container.querySelector(`.${CLASSNAME_GLOBAL_SEARCH}`)
            ).toBeInTheDocument();
            expect(
                container.querySelector(`.${CLASSNAME_CLOSE_OVERLAY}`)
            ).toBeInTheDocument();
        } else {
            expect(
                container.querySelector(`.${CLASSNAME_GLOBAL_SEARCH}`)
            ).toBeNull();
            expect(
                container.querySelector(`.${CLASSNAME_CLOSE_OVERLAY}`)
            ).toBeNull();
        }
    };

    describe('user is not authorized', () => {
        test('returns null', () => {
            const { container } = renderComponent(createIdentity({}));
            expect(container.firstChild).toBeNull();
        });
    });

    describe('user is authorized', () => {
        const identity = createIdentity({ id: 1 });
        jest.spyOn(identity, 'hasPermission').mockReturnValue(true);

        describe.each([
            ['once', 1],
            ['twice', 2],
            ['trice', 3],
        ])('icon clicked %s', (name, n) => {
            const shows = n % 2 !== 0;

            // eslint-disable-next-line jest/expect-expect
            test(`${
                shows ? 'shows' : 'hides'
            } the global search component`, () => {
                const { container } = renderComponent(identity);
                const icon = container.querySelector(`.${CLASSNAME_ICON}`);
                for (let i = 0; i < n; i++) if (icon) fireEvent.click(icon);

                expectSearchVisible(container, shows);
            });
        });

        describe.each([CLASSNAME_CLOSE_BTN, CLASSNAME_CLOSE_OVERLAY])(
            '".%s" clicked',
            className => {
                // eslint-disable-next-line jest/expect-expect
                test('hides the global search component', () => {
                    const { container } = renderComponent(identity);
                    const icon = container.querySelector(`.${CLASSNAME_ICON}`);
                    if (icon) fireEvent.click(icon);
                    expectSearchVisible(container, true);

                    const closeEl = container.querySelector(`.${className}`);
                    if (closeEl) fireEvent.click(closeEl);
                    expectSearchVisible(container, false);
                });
            }
        );
    });
});
