import React from 'react'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import * as UIModule from '@aws-amplify/ui'; import { Button, ButtonProps, Flex, Heading, Text, } from '../../../../primitives'; import { ComponentClassName } from '../../constants'; import { DeleteUserComponents, WarningViewProps } from '../types'; import DeleteUser from '../DeleteUser'; jest.mock('../../../../internal', () => ({ useAuth: () => ({ user: {} as unknown as UIModule.AmplifyUser, isLoading: false, }), })); const deleteUserSpy = jest.spyOn(UIModule, 'deleteUser'); function CustomWarningView({ onCancel, onConfirm }: WarningViewProps) { return ( Custom Warning Message ); } const CustomDeleteButton = ({ onClick, isDisabled }: ButtonProps) => { return ( ); }; const CustomErrorMessage = ({ children }) => ( <> Custom Error Message {children} ); const components: DeleteUserComponents = { DeleteButton: CustomDeleteButton, WarningView: CustomWarningView, ErrorMessage: CustomErrorMessage, }; describe('DeleteUser', () => { beforeEach(() => { jest.clearAllMocks(); }); it('renders as expected', () => { const { container } = render(); expect(container).toMatchSnapshot(); const deleteUser = container.getElementsByClassName( ComponentClassName.DeleteUser ); expect(deleteUser).toHaveLength(1); }); it('calls deleteUser with expected arguments', async () => { deleteUserSpy.mockResolvedValue(); const onSuccess = jest.fn(); render(); const deleteAccountButton = await screen.findByRole('button', { name: 'Delete Account', }); fireEvent.click(deleteAccountButton); const confirmDeleteButton = await screen.findByRole('button', { name: 'Delete my account', }); fireEvent.click(confirmDeleteButton); expect(deleteUserSpy).toBeCalledTimes(1); }); it('onSuccess is called after successful account deletion', async () => { deleteUserSpy.mockResolvedValue(); const onSuccess = jest.fn(); render(); const deleteAccountButton = await screen.findByRole('button', { name: 'Delete Account', }); fireEvent.click(deleteAccountButton); const confirmDeleteButton = await screen.findByRole('button', { name: 'Delete my account', }); fireEvent.click(confirmDeleteButton); // submit handling is async, wait for onSuccess to be called // https://testing-library.com/docs/dom-testing-library/api-async/#waitfor await waitFor(() => expect(onSuccess).toBeCalledTimes(1)); }); it('onError is called after unsuccessful submit', async () => { deleteUserSpy.mockRejectedValue(new Error('Mock Error')); const onError = jest.fn(); render(); const deleteAccountButton = await screen.findByRole('button', { name: 'Delete Account', }); fireEvent.click(deleteAccountButton); const confirmDeleteButton = await screen.findByRole('button', { name: 'Delete my account', }); fireEvent.click(confirmDeleteButton); // submit handling is async, wait for onError to be called await waitFor(() => expect(onError).toBeCalledTimes(1)); }); it('hides warning component if cancel is clicked', async () => { deleteUserSpy.mockResolvedValue(); render(); const deleteAccountButton = await screen.findByRole('button', { name: 'Delete Account', }); fireEvent.click(deleteAccountButton); // warning window now should be visible await screen.findByText('Delete my account'); const cancelButton = await screen.findByRole('button', { name: 'Cancel', }); fireEvent.click(cancelButton); // warning window should be gone now await waitFor(() => expect(screen.queryByText('Delete my account')).not.toBeInTheDocument() ); }); it('error message is displayed after unsuccessful submit', async () => { deleteUserSpy.mockRejectedValue(new Error('Mock Error')); const onError = jest.fn(); render(); const deleteAccountButton = await screen.findByRole('button', { name: 'Delete Account', }); fireEvent.click(deleteAccountButton); const confirmDeleteButton = await screen.findByRole('button', { name: 'Delete my account', }); fireEvent.click(confirmDeleteButton); expect(await screen.findByText('Mock Error')).toBeDefined(); }); it('renders as expected with components overrides', async () => { const { container } = render(); const submitButton = await screen.findByRole('button', { name: 'Custom Delete Button', }); expect(submitButton).toBeDefined(); expect(container).toMatchSnapshot(); fireEvent.click(submitButton); expect(await screen.findByText('Custom Warning Message')).toBeDefined(); }); it('onSuccess is called with component overrides after successful user deletion', async () => { deleteUserSpy.mockResolvedValue(); const onSuccess = jest.fn(); render(); const deleteAccountButton = await screen.findByRole('button', { name: 'Custom Delete Button', }); fireEvent.click(deleteAccountButton); const confirmDeleteButton = await screen.findByRole('button', { name: 'Custom Confirm Button', }); fireEvent.click(confirmDeleteButton); // submit handling is async, wait for onSuccess to be called // https://testing-library.com/docs/dom-testing-library/api-async/#waitfor await waitFor(() => expect(onSuccess).toBeCalledTimes(1)); }); it('calls deleteUser with expected arguments and component overrides', async () => { deleteUserSpy.mockResolvedValue(); const onSuccess = jest.fn(); render(); const deleteAccountButton = await screen.findByRole('button', { name: 'Custom Delete Button', }); fireEvent.click(deleteAccountButton); const confirmDeleteButton = await screen.findByRole('button', { name: 'Custom Confirm Button', }); fireEvent.click(confirmDeleteButton); expect(deleteUserSpy).toBeCalledWith(); expect(deleteUserSpy).toBeCalledTimes(1); }); it('error message is displayed with component overrides after unsuccessful submit', async () => { deleteUserSpy.mockRejectedValue(new Error('Mock Error')); render(); const deleteAccountButton = await screen.findByRole('button', { name: 'Custom Delete Button', }); fireEvent.click(deleteAccountButton); const confirmDeleteButton = await screen.findByRole('button', { name: 'Custom Confirm Button', }); fireEvent.click(confirmDeleteButton); await screen.findByText('Mock Error'); expect(await screen.findByText('Custom Error Message')).toBeDefined(); }); });