-
Notifications
You must be signed in to change notification settings - Fork 292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(account-settings): Enable component override for <DeleteUser /> #3123
Changes from 7 commits
479d66e
301156f
db508b8
4bc4c32
56b29e6
15bc0ff
9c97418
45ca1e2
bb9561a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,8 +1,16 @@ | ||||||
import React from 'react'; | ||||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react'; | ||||||
import { | ||||||
render, | ||||||
screen, | ||||||
fireEvent, | ||||||
waitFor, | ||||||
act, | ||||||
} from '@testing-library/react'; | ||||||
|
||||||
import * as UIModule from '@aws-amplify/ui'; | ||||||
|
||||||
import { Button, Flex, Heading, Text } from '../../../../primitives'; | ||||||
import { DeleteUserComponents } from '../types'; | ||||||
import DeleteUser from '../DeleteUser'; | ||||||
|
||||||
const user = {} as unknown as UIModule.AmplifyUser; | ||||||
|
@@ -15,6 +23,29 @@ jest.mock('../../../../internal', () => ({ | |||||
|
||||||
const deleteUserSpy = jest.spyOn(UIModule, 'deleteUser'); | ||||||
|
||||||
function CustomWarning({ onCancel, onConfirm, isDisabled }) { | ||||||
return ( | ||||||
<Flex direction="column"> | ||||||
<Text variation="warning">Custom Warning Message</Text> | ||||||
<Button onClick={onCancel}>Back</Button> | ||||||
<Button variation="primary" onClick={onConfirm} isDisabled={isDisabled}> | ||||||
Custom Confirm Button | ||||||
</Button> | ||||||
</Flex> | ||||||
); | ||||||
} | ||||||
|
||||||
const components: DeleteUserComponents = { | ||||||
SubmitButton: (props) => <Button {...props}>Custom Delete Button</Button>, | ||||||
Warning: (props) => <CustomWarning {...props} />, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be able to just write this as:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in bb9561a 😈 |
||||||
Error: ({ children }) => ( | ||||||
<> | ||||||
<Heading>Custom Error Message</Heading> | ||||||
<Text>{children}</Text> | ||||||
</> | ||||||
), | ||||||
}; | ||||||
|
||||||
describe('ChangePassword', () => { | ||||||
beforeEach(() => { | ||||||
jest.clearAllMocks(); | ||||||
|
@@ -133,7 +164,88 @@ describe('ChangePassword', () => { | |||||
|
||||||
fireEvent.click(confirmDeleteButton); | ||||||
|
||||||
// submit handling is async, wait for error to be displayed | ||||||
await waitFor(() => expect(screen.findByText('Mock Error')).toBeDefined()); | ||||||
expect(await screen.findByText('Mock Error')).toBeDefined(); | ||||||
}); | ||||||
|
||||||
it('renders as expected with components overrides', async () => { | ||||||
const { container } = render(<DeleteUser components={components} />); | ||||||
|
||||||
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(<DeleteUser components={components} onSuccess={onSuccess} />); | ||||||
|
||||||
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(<DeleteUser components={components} onSuccess={onSuccess} />); | ||||||
|
||||||
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(<DeleteUser components={components} />); | ||||||
|
||||||
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(); | ||||||
}); | ||||||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,35 @@ | ||
import React from 'react'; | ||
|
||
import { AmplifyUser } from '@aws-amplify/ui'; | ||
|
||
export interface DeleteUserWarningProps { | ||
import { ErrorComponent, SubmitButtonComponent } from '../types'; | ||
|
||
export interface WarningProps { | ||
/** called when end user cancels account deletion */ | ||
onCancel?: () => void; | ||
onCancel: () => void; | ||
/** called when user acknowledges account deletion */ | ||
onConfirm?: () => void; | ||
onConfirm: () => void; | ||
/** whether account deletion is in progress */ | ||
isDisabled?: boolean; | ||
isDisabled: boolean; | ||
Comment on lines
-5
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Made these required, because parent component always pass those in to the |
||
} | ||
|
||
export type WarningComponent<Props = {}> = React.ComponentType< | ||
Props & WarningProps | ||
>; | ||
|
||
export type DeleteUserState = | ||
| 'IDLE' | ||
| 'CONFIRMATION' | ||
| 'DELETING' | ||
| 'DONE' | ||
| 'ERROR'; | ||
|
||
export interface DeleteUserComponents { | ||
Error?: ErrorComponent; | ||
SubmitButton?: SubmitButtonComponent; | ||
Warning?: WarningComponent; | ||
} | ||
|
||
export interface DeleteUserProps { | ||
/** custom delete user service override */ | ||
handleDelete?: (user: AmplifyUser) => Promise<void> | void; | ||
|
@@ -25,4 +39,7 @@ export interface DeleteUserProps { | |
|
||
/** callback for unsuccessful user deletion */ | ||
onError?: (error: Error) => void; | ||
|
||
/** custom component overrides */ | ||
components?: DeleteUserComponents; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nittish, prefer nullish coalescing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 45ca1e2 for both
DeleteUser
andChangePassword