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