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');
});
});
});