import { PropsWithChildren } from 'react'; import { QueryClient, QueryClientProvider, useMutation, UseMutationResult, } from 'react-query'; import { ToastProvider } from '../toast/ToastProvider'; import { act, render, screen, waitFor, within, } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { InlineInput } from './InlineInput'; const queryClient = new QueryClient(); const Wrapper = ({ children }: PropsWithChildren<{}>) => { return ( {children} ); }; const ChangeMutationProvider = ({ onChange, children, }: { onChange: (value: string) => void; children: ({ changeMutation, }: { changeMutation: UseMutationResult; }) => JSX.Element; }) => { const changeMutation = useMutation({ mutationFn: ({ value }) => { return new Promise((resolve) => { onChange(value); resolve(null); }); }, }); return <>{children({ changeMutation })}; }; const selectors = { confirmationModal: () => screen.getByRole('dialog', { name: /Confirm/i }), }; describe('InlineInput', () => { describe('when the user clicks accepts the edit', () => { test('without confirmation modal', async () => { //S const mock = jest.fn(); render( {({ changeMutation }) => ( )} , { wrapper: Wrapper }, ); await waitFor(() => screen.findByRole('img', { hidden: true })); //E /// First focus the edit button await userEvent.tab(); /// Then press enter to edit the input await act(() => userEvent.keyboard('{enter}')); /// Then type a new value await act(() => userEvent.type(document.activeElement!, 'new value')); /// Then press enter to confirm the new value await act(() => userEvent.keyboard('{enter}')); await waitFor(() => screen.findByText('testnew value')); expect(screen.queryByRole('textbox')).not.toBeInTheDocument(); //V expect(mock).toHaveBeenCalledWith('testnew value'); expect(mock).toHaveBeenCalledTimes(1); expect(screen.getByText('testnew value')).toBeInTheDocument(); }); test('with confirmation modal', async () => { //S const mock = jest.fn(); render( {({ changeMutation }) => ( Confirm, body:
Are you sure?
, }} /> )}
, { wrapper: Wrapper }, ); await waitFor(() => screen.findByRole('img', { hidden: true })); //E /// First focus the edit button await userEvent.tab(); /// Then press enter to edit the input await act(() => userEvent.keyboard('{enter}')); /// Then type a new value await act(() => userEvent.type(document.activeElement!, 'new value')); /// Then press enter to confirm the new value await act(() => userEvent.keyboard('{enter}')); await waitFor(() => screen.findByRole('dialog', { name: /Confirm/i })); /// Expect the confirmation modal to be opened expect(selectors.confirmationModal()).toBeInTheDocument() /// Click the confirm button await act(() => userEvent.click(screen.getByRole('button', { name: /confirm/i }))); /// modal should be closed expect(screen.queryByRole('dialog', { name: /Confirm/i })).not.toBeInTheDocument(); //V expect(mock).toHaveBeenCalledWith('testnew value'); expect(mock).toHaveBeenCalledTimes(1); expect(screen.getByText('testnew value')).toBeInTheDocument(); }); }); describe('when the user clicks reset the edit', () => { test('without confirmation modal', async () => { //S const mock = jest.fn(); render( {({ changeMutation }) => ( )} , { wrapper: Wrapper }, ); await waitFor(() => screen.findByRole('img', { hidden: true })); //E /// First focus the edit button await userEvent.tab(); /// Then press enter to edit the input await act(() => userEvent.keyboard('{enter}')); /// Then type a new value await act(() => userEvent.type(document.activeElement!, 'new value')); /// Then press escape to cancel the new value await act(() => userEvent.keyboard('{esc}')); //V expect(mock).not.toHaveBeenCalled(); expect(screen.getByText('test')).toBeInTheDocument(); }); test('with confirmation modal', async () => { //S const mock = jest.fn(); render( {({ changeMutation }) => ( Confirm, body:
Are you sure?
, }} /> )}
, { wrapper: Wrapper }, ); await waitFor(() => screen.findByRole('img', { hidden: true })); //E /// First focus the edit button await userEvent.tab(); /// Then press enter to edit the input await act(() => userEvent.keyboard('{enter}')); /// Then type a new value await act(() => userEvent.type(document.activeElement!, 'new value')); /// Then press enter to confirm the new value await act(() => userEvent.keyboard('{enter}')); /// Expect the confirmation modal to be opened await waitFor(() => expect(selectors.confirmationModal()).toBeInTheDocument(), ); /// Click the cancel button await userEvent.click( within(selectors.confirmationModal()).getByRole('button', { name: /Cancel/i, }), ); //V expect(mock).not.toHaveBeenCalled(); expect(screen.getByRole('textbox')).toBeInTheDocument(); expect((screen.getByRole('textbox') as HTMLInputElement).value).toBe('testnew value'); }); }); });