RocketChat/Rocket.Chat

View on GitHub
apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx

Summary

Maintainability
A
2 hrs
Test Coverage
import { useSetModal } from '@rocket.chat/ui-contexts';
import { act, render, screen } from '@testing-library/react';
import type { ForwardedRef, ReactElement } from 'react';
import React, { Suspense, createContext, createRef, forwardRef, useContext, useImperativeHandle } from 'react';

import GenericModal from '../../components/GenericModal';
import { imperativeModal } from '../../lib/imperativeModal';
import ModalRegion from '../../views/modal/ModalRegion';
import ModalProvider from './ModalProvider';
import ModalProviderWithRegion from './ModalProviderWithRegion';

const renderWithSuspense = (ui: ReactElement) =>
    render(ui, {
        legacyRoot: true,
        wrapper: ({ children }) => <Suspense fallback={null}>{children}</Suspense>,
    });

describe('via useSetModal', () => {
    const ModalTitleContext = createContext('default');

    type ModalOpenerAPI = { open: () => void };

    const ModalOpener = forwardRef((_: unknown, ref: ForwardedRef<ModalOpenerAPI>) => {
        const setModal = useSetModal();
        const title = useContext(ModalTitleContext);
        useImperativeHandle(ref, () => ({
            open: () => {
                setModal(<GenericModal open title={title} />);
            },
        }));

        return null;
    });

    it('should render a modal', async () => {
        const modalOpenerRef = createRef<ModalOpenerAPI>();

        renderWithSuspense(
            <ModalProviderWithRegion>
                <ModalOpener ref={modalOpenerRef} />
            </ModalProviderWithRegion>,
        );

        act(() => {
            modalOpenerRef.current?.open();
        });

        expect(await screen.findByRole('dialog', { name: 'default' })).toBeInTheDocument();
    });

    it('should render a modal that consumes a context', async () => {
        const modalOpenerRef = createRef<ModalOpenerAPI>();

        renderWithSuspense(
            <ModalTitleContext.Provider value='title from context'>
                <ModalProviderWithRegion>
                    <ModalOpener ref={modalOpenerRef} />
                </ModalProviderWithRegion>
            </ModalTitleContext.Provider>,
        );
        act(() => {
            modalOpenerRef.current?.open();
        });

        expect(await screen.findByRole('dialog', { name: 'title from context' })).toBeInTheDocument();
    });

    it('should render a modal in another region', async () => {
        const modalOpener1Ref = createRef<ModalOpenerAPI>();
        const modalOpener2Ref = createRef<ModalOpenerAPI>();

        renderWithSuspense(
            <ModalTitleContext.Provider value='modal1'>
                <ModalProviderWithRegion>
                    <ModalOpener ref={modalOpener1Ref} />
                </ModalProviderWithRegion>
                <ModalTitleContext.Provider value='modal2'>
                    <ModalProviderWithRegion>
                        <ModalOpener ref={modalOpener2Ref} />
                    </ModalProviderWithRegion>
                </ModalTitleContext.Provider>
            </ModalTitleContext.Provider>,
        );

        act(() => {
            modalOpener1Ref.current?.open();
        });

        expect(await screen.findByRole('dialog', { name: 'modal1' })).toBeInTheDocument();

        act(() => {
            modalOpener2Ref.current?.open();
        });

        expect(await screen.findByRole('dialog', { name: 'modal2' })).toBeInTheDocument();
    });
});

describe('via imperativeModal', () => {
    it('should render a modal through imperative modal', async () => {
        renderWithSuspense(
            <ModalProvider>
                <ModalRegion />
            </ModalProvider>,
        );

        act(() => {
            imperativeModal.open({
                component: GenericModal,
                props: { title: 'imperativeModal', open: true },
            });
        });

        expect(await screen.findByRole('dialog', { name: 'imperativeModal' })).toBeInTheDocument();

        act(() => {
            imperativeModal.close();
        });

        expect(screen.queryByText('imperativeModal')).not.toBeInTheDocument();
    });

    it('should not render a modal if no corresponding region exists', async () => {
        // ModalProviderWithRegion will always have a region identifier set
        // and imperativeModal will only render modals in the default region (e.g no region identifier)

        renderWithSuspense(<ModalProviderWithRegion />);

        act(() => {
            imperativeModal.open({
                component: GenericModal,
                props: { title: 'imperativeModal', open: true },
            });
        });

        expect(screen.queryByRole('dialog', { name: 'imperativeModal' })).not.toBeInTheDocument();
    });
});