diff --git a/src/constants/translations/en/edit-profile.json b/src/constants/translations/en/edit-profile.json index f1d42b1fa..543bceee7 100644 --- a/src/constants/translations/en/edit-profile.json +++ b/src/constants/translations/en/edit-profile.json @@ -72,13 +72,15 @@ "passwordSecurityTab": { "tabTitle": "Password & Security", "title": "Password & Security", + "subTitle": "You can change your password using the current one.", "description": "Change password and security settings", "changePassword": "Change password", + "changePasswordModalDescription": "Reset your current password to new one.", "changePasswordConfirm": "Are you sure you want to change the password?", "currentPassword": "Current password", "newPassword": "New password", "retypePassword": "Re-type new password", - "savePassword": "Save new password", + "savePassword": "Save the password", "deactivateAccount": "Deactivate account", "deactivateBtn": "Deactivate", "deactivateTitle": "Deactivate your account?", diff --git a/src/constants/translations/uk/edit-profile.json b/src/constants/translations/uk/edit-profile.json index 15775a79c..d1d724a57 100644 --- a/src/constants/translations/uk/edit-profile.json +++ b/src/constants/translations/uk/edit-profile.json @@ -72,8 +72,10 @@ "passwordSecurityTab": { "tabTitle": "Пароль і Безпека", "title": "Пароль і Безпека", + "subTitle": "Ви можете змінити свій пароль, використовуючи поточний.", "description": "Зміна паролю та налаштуваннь безпеки", "changePassword": "Змінити пароль", + "changePasswordModalDescription": "Змінити поточний пароль на новий.", "changePasswordConfirm": "Ви впевнені, що бажаєте змінити пароль?", "currentPassword": "Поточний пароль", "newPassword": "Новий пароль", diff --git a/src/containers/edit-profile/password-security-tab/PasswordSecurityTab.styles.ts b/src/containers/edit-profile/password-security-tab/PasswordSecurityTab.styles.ts index 768375f7d..17725fb65 100644 --- a/src/containers/edit-profile/password-security-tab/PasswordSecurityTab.styles.ts +++ b/src/containers/edit-profile/password-security-tab/PasswordSecurityTab.styles.ts @@ -4,14 +4,12 @@ import { rootContainer } from '~/containers/edit-profile/common.styles' export const styles = { container: rootContainer, titleAndDescription: { - title: { - typography: TypographyVariantEnum.H6 - }, - description: { - typography: TypographyVariantEnum.Body2, - color: 'primary.500', - mb: '30px' - } + typography: TypographyVariantEnum.H5 + }, + description: { + typography: TypographyVariantEnum.Subtitle1, + color: 'primary.500', + mb: '30px' }, subtitle: { typography: TypographyVariantEnum.Body1, @@ -20,13 +18,9 @@ export const styles = { form: { display: 'flex', flexDirection: 'column', gap: '8px' }, passwordButtonsContainer: { - m: '10px 0 20px', - display: 'grid', - gridTemplateColumns: { - sm: 'repeat(5, minmax(0, 1fr))', - md: 'repeat(7, minmax(0, 1fr))', - lg: 'repeat(10, minmax(0, 1fr))' - }, + display: 'flex', + justifyContent: 'flex-end', + alignItems: 'flex-end', gap: '10px' }, @@ -39,5 +33,12 @@ export const styles = { deactivateButton: { mt: '20px', backgroundColor: 'error.700' + }, + modalContainer: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: '700px', + position: 'relative' } } diff --git a/src/containers/edit-profile/password-security-tab/PasswordSecurityTab.tsx b/src/containers/edit-profile/password-security-tab/PasswordSecurityTab.tsx index 8ba263a83..a7b8b59fe 100644 --- a/src/containers/edit-profile/password-security-tab/PasswordSecurityTab.tsx +++ b/src/containers/edit-profile/password-security-tab/PasswordSecurityTab.tsx @@ -1,113 +1,26 @@ -import { useCallback, FC } from 'react' +import { FC } from 'react' import { useTranslation } from 'react-i18next' - import Box from '@mui/material/Box' -import Typography from '@mui/material/Typography' -import Divider from '@mui/material/Divider' - -import Loader from '~/components/loader/Loader' -import AppButton from '~/components/app-button/AppButton' -import AppTextField from '~/components/app-text-field/AppTextField' -import TitleWithDescription from '~/components/title-with-description/TitleWithDescription' -import { snackbarVariants } from '~/constants' -import useForm from '~/hooks/use-form' +import { useModalContext } from '~/context/modal-context' import useChangeUserStatus from '~/hooks/use-change-user-status' -import useAxios from '~/hooks/use-axios' -import { useAppDispatch, useAppSelector } from '~/hooks/use-redux' -import useInputVisibility from '~/hooks/use-input-visibility' -import useConfirm from '~/hooks/use-confirm' - -import { AuthService } from '~/services/auth-service' -import { openAlert } from '~/redux/features/snackbarSlice' +import PasswordSecurityItem from '~/containers/edit-profile/password-security-tab/password-security-item/PasswordSecurityItem' +import ChangePasswordModal from '~/containers/edit-profile/password-security-tab/change-password-modal/ChangePasswordModal' +import AppButton from '~/components/app-button/AppButton' import { styles } from '~/containers/edit-profile/password-security-tab/PasswordSecurityTab.styles' - -import { - ButtonVariantEnum, - ComponentEnum, - ButtonTypeEnum, - InputEnum, - SizeEnum, - FormValues, - ErrorResponse -} from '~/types' -import { - initialValues, - validations -} from '~/containers/edit-profile/password-security-tab/PasswordSecurityTab.constants' +import { ButtonVariantEnum, SizeEnum } from '~/types' const PasswordSecurityTab: FC = () => { const { t } = useTranslation() - const dispatch = useAppDispatch() - const { userId } = useAppSelector((state) => state.appMain) - const { checkConfirmation } = useConfirm() - + const { openModal } = useModalContext() const { neededAction, checkStatusChange } = useChangeUserStatus() - const handleSubmitChangePassword = async () => { - const confirmed = await checkConfirmation({ - message: t( - 'editProfilePage.profile.passwordSecurityTab.changePasswordConfirm' - ), - title: 'titles.confirmTitle', - check: true + const openChangePasswordModal = () => { + openModal({ + component: }) - if (confirmed) { - resetErrors() - await sendChangedPassword({ - password: data.password, - currentPassword: data.currentPassword - }) - } - } - - const handleResponse = () => { - dispatch( - openAlert({ - severity: snackbarVariants.success, - message: 'editProfilePage.profile.successMessage' - }) - ) - } - - const changePassword = useCallback( - (data: { password: string; currentPassword: string }) => { - return AuthService.changePassword(userId, data) - }, - [userId] - ) - - const handleResponseError = (error?: ErrorResponse) => { - if (error?.code === 'INCORRECT_CREDENTIALS') { - handleErrors('password', t('common.errorMessages.samePasswords')) - } else { - handleErrors('currentPassword', t('common.errorMessages.currentPassword')) - } } - - const { loading, fetchData: sendChangedPassword } = useAxios({ - service: changePassword, - onResponse: handleResponse, - onResponseError: handleResponseError, - fetchOnMount: false - }) - - const { - data, - handleSubmit, - handleInputChange, - errors, - handleBlur, - resetData, - resetErrors, - handleErrors - } = useForm({ - onSubmit: handleSubmitChangePassword, - initialValues: initialValues, - validations: validations - }) - const handleChangeStatusClick = () => { void checkStatusChange( `editProfilePage.profile.passwordSecurityTab.${neededAction}Title`, @@ -115,113 +28,27 @@ const PasswordSecurityTab: FC = () => { true ) } - - const { - inputVisibility: currentPasswordVisibility, - showInputText: showCurrentPassword - } = useInputVisibility(errors.currentPassword) - - const { inputVisibility: passwordVisibility, showInputText: showPassword } = - useInputVisibility(errors.password) - - const { - inputVisibility: newPasswordVisibility, - showInputText: showNewPassword - } = useInputVisibility(errors.confirmPassword) - - const onDiscard = () => { - resetData() - resetErrors() - } - - const saveButtonContent = loading ? ( - - ) : ( - t('editProfilePage.profile.passwordSecurityTab.savePassword') - ) - - const inputType = (isVisible: boolean) => - isVisible ? InputEnum.Text : InputEnum.Password - return ( - - + - - - {t('editProfilePage.profile.passwordSecurityTab.changePassword')} - - - - - - - - - {saveButtonContent} - - - {t('common.discard')} - - - - - {t( - `editProfilePage.profile.passwordSecurityTab.${neededAction}Account` - )} - - + + {t( + `editProfilePage.profile.passwordSecurityTab.${neededAction}Account` + )} + ) } diff --git a/src/containers/edit-profile/password-security-tab/change-password-modal/ChangePasswordModal.tsx b/src/containers/edit-profile/password-security-tab/change-password-modal/ChangePasswordModal.tsx new file mode 100644 index 000000000..7016e786a --- /dev/null +++ b/src/containers/edit-profile/password-security-tab/change-password-modal/ChangePasswordModal.tsx @@ -0,0 +1,211 @@ +import { useCallback } from 'react' +import { useTranslation } from 'react-i18next' +import Box from '@mui/material/Box' +import Typography from '@mui/material/Typography' + +import { useModalContext } from '~/context/modal-context' +import { AuthService } from '~/services/auth-service' +import useForm from '~/hooks/use-form' +import useAxios from '~/hooks/use-axios' +import useInputVisibility from '~/hooks/use-input-visibility' +import useConfirm from '~/hooks/use-confirm' + +import Loader from '~/components/loader/Loader' +import AppButton from '~/components/app-button/AppButton' +import AppTextField from '~/components/app-text-field/AppTextField' + +import { snackbarVariants } from '~/constants' + +import { useAppDispatch, useAppSelector } from '~/hooks/use-redux' +import { openAlert } from '~/redux/features/snackbarSlice' + +import { styles } from '~/containers/edit-profile/password-security-tab/PasswordSecurityTab.styles' + +import { + ButtonVariantEnum, + ComponentEnum, + ButtonTypeEnum, + InputEnum, + SizeEnum, + FormValues, + ErrorResponse +} from '~/types' +import { + initialValues, + validations +} from '~/containers/edit-profile/password-security-tab/PasswordSecurityTab.constants' + +const ChangePasswordModal = () => { + const { t } = useTranslation() + const dispatch = useAppDispatch() + const { userId } = useAppSelector((state) => state.appMain) + const { checkConfirmation } = useConfirm() + const { closeModal } = useModalContext() + + const handleSubmitChangePassword = async () => { + const confirmed = await checkConfirmation({ + message: t( + 'editProfilePage.profile.passwordSecurityTab.changePasswordConfirm' + ), + title: 'titles.confirmTitle', + check: true + }) + if (confirmed) { + resetErrors() + await sendChangedPassword({ + password: data.password, + currentPassword: data.currentPassword + }) + } + } + + const handleResponse = () => { + dispatch( + openAlert({ + severity: snackbarVariants.success, + message: 'editProfilePage.profile.successMessage' + }) + ) + closeModal() + } + + const changePassword = useCallback( + (data: { password: string; currentPassword: string }) => { + return AuthService.changePassword(userId, data) + }, + [userId] + ) + + const handleResponseError = (error?: ErrorResponse) => { + if (error?.code === 'INCORRECT_CREDENTIALS') { + handleErrors('password', t('common.errorMessages.samePasswords')) + } else { + handleErrors('currentPassword', t('common.errorMessages.currentPassword')) + } + } + + const { loading, fetchData: sendChangedPassword } = useAxios({ + service: changePassword, + onResponse: handleResponse, + onResponseError: handleResponseError, + fetchOnMount: false + }) + + const { + data, + handleSubmit, + handleInputChange, + errors, + handleBlur, + resetData, + resetErrors, + handleErrors + } = useForm({ + onSubmit: handleSubmitChangePassword, + initialValues: initialValues, + validations: validations + }) + + const { + inputVisibility: currentPasswordVisibility, + showInputText: showCurrentPassword + } = useInputVisibility(errors.currentPassword) + + const { inputVisibility: passwordVisibility, showInputText: showPassword } = + useInputVisibility(errors.password) + + const { + inputVisibility: newPasswordVisibility, + showInputText: showNewPassword + } = useInputVisibility(errors.confirmPassword) + + const onDiscard = () => { + resetData() + resetErrors() + closeModal() + } + + const saveButtonContent = loading ? ( + + ) : ( + t('editProfilePage.profile.passwordSecurityTab.savePassword') + ) + + const inputType = (isVisible: boolean) => + isVisible ? InputEnum.Text : InputEnum.Password + + return ( + + + + {t('editProfilePage.profile.passwordSecurityTab.changePassword')} + + + {t( + 'editProfilePage.profile.passwordSecurityTab.changePasswordModalDescription' + )} + + + + + + + + + + {t('common.cancel')} + + + {saveButtonContent} + + + + + + ) +} + +export default ChangePasswordModal diff --git a/src/containers/edit-profile/password-security-tab/password-security-item/PasswordSecurityItem.styles.ts b/src/containers/edit-profile/password-security-tab/password-security-item/PasswordSecurityItem.styles.ts new file mode 100644 index 000000000..b1af738ef --- /dev/null +++ b/src/containers/edit-profile/password-security-tab/password-security-item/PasswordSecurityItem.styles.ts @@ -0,0 +1,20 @@ +import { TypographyVariantEnum } from '~/types' + +export const styles = { + container: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'flex-start', + m: '20px 0' + }, + title: { + typography: TypographyVariantEnum.Button + }, + description: { + typography: TypographyVariantEnum.Body2, + color: 'primary.500' + }, + titlesAndButtonContainer: { + p: '20px 0' + } +} diff --git a/src/containers/edit-profile/password-security-tab/password-security-item/PasswordSecurityItem.tsx b/src/containers/edit-profile/password-security-tab/password-security-item/PasswordSecurityItem.tsx new file mode 100644 index 000000000..f52497684 --- /dev/null +++ b/src/containers/edit-profile/password-security-tab/password-security-item/PasswordSecurityItem.tsx @@ -0,0 +1,44 @@ +import { SxProps } from '@mui/material' +import Box from '@mui/material/Box' +import Typography from '@mui/material/Typography' +import { Theme } from '@emotion/react' + +import AppButton from '~/components/app-button/AppButton' +import AppCard from '~/components/app-card/AppCard' + +import { styles } from '~/containers/edit-profile/password-security-tab/password-security-item/PasswordSecurityItem.styles' +import { ButtonVariantEnum, SizeEnum } from '~/types' + +interface PasswordSecurityItemProps { + title: string + description: string + buttonText: string + onClick: () => void + sx?: SxProps +} + +const PasswordSecurityItem = ({ + title, + description, + buttonText, + onClick, + sx +}: PasswordSecurityItemProps) => ( + + + {title} + {description} + + + + {buttonText} + + +) + +export default PasswordSecurityItem diff --git a/tests/unit/containers/edit-profile/password-security-tab/ChangePasswordModal.spec.jsx b/tests/unit/containers/edit-profile/password-security-tab/ChangePasswordModal.spec.jsx new file mode 100644 index 000000000..d466cc8fb --- /dev/null +++ b/tests/unit/containers/edit-profile/password-security-tab/ChangePasswordModal.spec.jsx @@ -0,0 +1,200 @@ +import { vi } from 'vitest' +import { screen, fireEvent, waitFor } from '@testing-library/react' +import { + renderWithProviders, + mockAxiosClient, + TestSnackbar +} from '~tests/test-utils' +import ChangePasswordModal from '~/containers/edit-profile/password-security-tab/change-password-modal/ChangePasswordModal' +import { AuthService } from '~/services/auth-service' +import { URLs } from '~/constants/request' + +const userDataMock = { + _id: 123456 +} + +const handleSubmit = vi.fn() + +vi.mock('~/services/auth-service', () => ({ + AuthService: { + changePassword: vi.fn() + } +})) + +const renderChangePasswordModal = () => { + renderWithProviders( + + + , + { + preloadedState: { + appMain: { + userId: userDataMock._id, + userStatus: 'active' + } + } + } + ) +} + +describe('ChangePasswordModal', () => { + beforeEach(() => { + renderChangePasswordModal() + }) + + it('should save data after positive response', async () => { + mockAxiosClient + .onPatch(`${URLs.auth.changePassword}/${userDataMock._id}`) + .reply(200) + + const currentPasswordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.currentPassword/i + ) + const passwordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.newPassword/i + ) + const confirmPasswordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.retypePassword/i + ) + const saveButton = screen.getByText( + /editProfilePage.profile.passwordSecurityTab.savePassword/i + ) + + fireEvent.change(currentPasswordInput, { + target: { value: '12345qwert' } + }) + fireEvent.change(passwordInput, { + target: { value: '12345qwertY' } + }) + fireEvent.change(confirmPasswordInput, { + target: { value: '12345qwertY' } + }) + + await waitFor(() => { + fireEvent.click(saveButton) + }) + + const confirmButton = screen.getByText('common.yes') + fireEvent.click(confirmButton) + + await waitFor(() => { + expect(AuthService.changePassword).toHaveBeenCalledWith( + userDataMock._id, + { + password: '12345qwertY', + currentPassword: '12345qwert' + } + ) + }) + }) + + it('should not save data after negative response', async () => { + mockAxiosClient + .onPatch(`${URLs.auth.changePassword}/${userDataMock._id}`) + .reply(400, { + message: 'new password cannot be the same as the current one' + }) + + const currentPasswordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.currentPassword/i + ) + const passwordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.newPassword/i + ) + const confirmPasswordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.retypePassword/i + ) + const saveButton = screen.getByText( + /editProfilePage.profile.passwordSecurityTab.savePassword/i + ) + + fireEvent.change(currentPasswordInput, { + target: { value: '12345qwertY' } + }) + fireEvent.change(passwordInput, { + target: { value: '12345qwertY' } + }) + fireEvent.change(confirmPasswordInput, { + target: { value: '12345qwertY' } + }) + + await waitFor(() => { + fireEvent.click(saveButton) + }) + + expect(handleSubmit).not.toHaveBeenCalled() + }) + + it('should not save empty fields', () => { + const currentPasswordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.currentPassword/i + ) + const passwordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.newPassword/i + ) + const confirmPasswordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.retypePassword/i + ) + const saveButton = screen.getByText( + /editProfilePage.profile.passwordSecurityTab.savePassword/i + ) + + fireEvent.change(currentPasswordInput, { + target: { value: '' } + }) + fireEvent.change(passwordInput, { + target: { value: '' } + }) + fireEvent.change(confirmPasswordInput, { + target: { value: '' } + }) + + fireEvent.click(saveButton) + + expect(handleSubmit).not.toHaveBeenCalled() + expect(currentPasswordInput).toHaveValue('') + expect(passwordInput).toHaveValue('') + expect(confirmPasswordInput).toHaveValue('') + }) + + it('should show visibility icon', async () => { + const visibilityOffIcons = screen.getAllByTestId('VisibilityOffIcon') + const visibilityOffIcon = visibilityOffIcons[0] + fireEvent.click(visibilityOffIcon) + + const visibilityIcons = screen.getAllByTestId('VisibilityIcon') + const visibilityIcon = visibilityIcons[0] + await waitFor(() => { + expect(visibilityIcon).toBeInTheDocument() + expect(visibilityOffIcon).not.toBeInTheDocument() + }) + }) + + it('resets form when discard button is clicked', () => { + const currentPasswordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.currentPassword/i + ) + const passwordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.newPassword/i + ) + const confirmPasswordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.retypePassword/i + ) + const discardButton = screen.getByText('common.cancel') + + fireEvent.change(passwordInput, { target: { value: 'oldPassword' } }) + fireEvent.click(discardButton) + + expect(currentPasswordInput).toHaveValue('') + expect(passwordInput).toHaveValue('') + expect(confirmPasswordInput).toHaveValue('') + }) + + it('updates state when form fields are changed', () => { + const currentPasswordInput = screen.getByLabelText( + /editProfilePage.profile.passwordSecurityTab.currentPassword/i + ) + fireEvent.change(currentPasswordInput, { target: { value: 'oldPassword' } }) + expect(currentPasswordInput).toHaveValue('oldPassword') + }) +}) diff --git a/tests/unit/containers/edit-profile/password-security-tab/PasswordSecurityTab.spec.jsx b/tests/unit/containers/edit-profile/password-security-tab/PasswordSecurityTab.spec.jsx index 832d4e5e0..db441a7e9 100644 --- a/tests/unit/containers/edit-profile/password-security-tab/PasswordSecurityTab.spec.jsx +++ b/tests/unit/containers/edit-profile/password-security-tab/PasswordSecurityTab.spec.jsx @@ -2,18 +2,10 @@ import { vi } from 'vitest' import { screen, fireEvent, - waitFor, waitForElementToBeRemoved } from '@testing-library/react' -import { - renderWithProviders, - mockAxiosClient, - TestSnackbar -} from '~tests/test-utils' +import { renderWithProviders, TestSnackbar } from '~tests/test-utils' import PasswordSecurityTab from '~/containers/edit-profile/password-security-tab/PasswordSecurityTab' -import { AuthService } from '~/services/auth-service' - -import { URLs } from '~/constants/request' const userDataMock = { _id: 123456 @@ -25,34 +17,6 @@ vi.mock('~/services/auth-service', () => ({ } })) -const handleSubmit = vi.fn() - -const changeInputValue = (label, value) => { - fireEvent.change(label, { target: { value } }) -} - -const setupChangePasswordFields = () => { - const currentPasswordInput = screen.getByLabelText( - /editProfilePage.profile.passwordSecurityTab.currentPassword/i - ) - const passwordInput = screen.getByLabelText( - /editProfilePage.profile.passwordSecurityTab.newPassword/i - ) - const confirmPasswordInput = screen.getByLabelText( - /editProfilePage.profile.passwordSecurityTab.retypePassword/i - ) - const saveButton = screen.getByText( - /editProfilePage.profile.passwordSecurityTab.savePassword/i - ) - - return { - currentPasswordInput, - passwordInput, - confirmPasswordInput, - saveButton - } -} - const renderWithMockData = () => { renderWithProviders( @@ -74,148 +38,18 @@ describe('PasswordSecurityTab', () => { renderWithMockData() }) - it('should save data after positive response', async () => { - mockAxiosClient - .onPatch(`${URLs.auth.changePassword}/${userDataMock}`) - .reply(200) - - const { - currentPasswordInput, - passwordInput, - confirmPasswordInput, - saveButton - } = setupChangePasswordFields() - - fireEvent.change(currentPasswordInput, { - target: { value: '12345qwert' } - }) - fireEvent.change(passwordInput, { - target: { value: '12345qwertY' } - }) - fireEvent.change(confirmPasswordInput, { - target: { value: '12345qwertY' } - }) - - await waitFor(() => { - fireEvent.click(saveButton) - }) - - const confirmButton = screen.getByText('common.yes') - fireEvent.click(confirmButton) - - await waitFor(() => { - expect(AuthService.changePassword).toHaveBeenCalledWith( - userDataMock._id, - { - password: '12345qwertY', - currentPassword: '12345qwert' - } - ) - }) - }) - - it('should not save data after negative response', async () => { - mockAxiosClient - .onPatch(`${URLs.auth.changePassword}/${userDataMock}`) - .reply(400, { - message: 'new password cannot be the same as the current one' - }) - - const { - currentPasswordInput, - passwordInput, - confirmPasswordInput, - saveButton - } = setupChangePasswordFields() - - fireEvent.change(currentPasswordInput, { - target: { value: '12345qwertY' } - }) - fireEvent.change(passwordInput, { - target: { value: '12345qwertY' } - }) - fireEvent.change(confirmPasswordInput, { - target: { value: '12345qwertY' } - }) - - await waitFor(() => { - fireEvent.click(saveButton) - }) - expect(handleSubmit).not.toHaveBeenCalled() - }) - - it('should do not save empty fields', async () => { - const { - currentPasswordInput, - passwordInput, - confirmPasswordInput, - saveButton - } = setupChangePasswordFields() - - fireEvent.change(currentPasswordInput, { - target: { value: '' } - }) - fireEvent.change(passwordInput, { - target: { value: '' } - }) - fireEvent.change(confirmPasswordInput, { - target: { value: '' } - }) - - fireEvent.click(saveButton) - - expect(handleSubmit).not.toHaveBeenCalled() - - expect(currentPasswordInput).toHaveValue('') - expect(passwordInput).toHaveValue('') - expect(confirmPasswordInput).toHaveValue('') - }) - - it('should show visibility icon', async () => { - const visibilityOffIcons = screen.getAllByTestId('VisibilityOffIcon') - const visibilityOffIcon = visibilityOffIcons[0] - fireEvent.click(visibilityOffIcon) - - const visibilityIcons = screen.getAllByTestId('VisibilityIcon') - const visibilityIcon = visibilityIcons[0] - await waitFor(() => { - expect(visibilityIcon).toBeInTheDocument() - expect(visibilityOffIcon).not.toBeInTheDocument() - }) - }) - it('renders title and description', () => { const title = screen.getByText( 'editProfilePage.profile.passwordSecurityTab.title' ) const description = screen.getByText( - 'editProfilePage.profile.passwordSecurityTab.description' + 'editProfilePage.profile.passwordSecurityTab.subTitle' ) expect(title).toBeInTheDocument() expect(description).toBeInTheDocument() }) - it('resets form when discard button is clicked', () => { - const { currentPasswordInput } = setupChangePasswordFields() - - const discardButtonText = screen.getByText('common.discard') - - changeInputValue(currentPasswordInput, 'oldPassword') - - fireEvent.click(discardButtonText) - - expect(currentPasswordInput).toHaveValue('') - }) - - it('updates state when form fields are changed', () => { - const { currentPasswordInput } = setupChangePasswordFields() - - changeInputValue(currentPasswordInput, 'oldPassword') - - expect(currentPasswordInput).toHaveValue('oldPassword') - }) - - it('checks is ConfirmDialog open when deactivate account button is clicked', () => { + it('checks if ConfirmDialog is open when deactivate account button is clicked', () => { const deactivateAccountButton = screen.getByText( 'editProfilePage.profile.passwordSecurityTab.deactivateAccount' ) @@ -228,7 +62,7 @@ describe('PasswordSecurityTab', () => { expect(deactivateTitle).toBeInTheDocument() }) - it('checks is ConfirmDialog closed when cancel button is clicked', async () => { + it('checks if ConfirmDialog is closed when cancel button is clicked', async () => { const deactivateAccountButton = screen.getByText( 'editProfilePage.profile.passwordSecurityTab.deactivateAccount' )