import { render , screen , waitFor } from '@testing-library/react' ; import userEvent from '@testing-library/user-event' ; import { mocked } from 'ts-jest/utils' ; import API from '../../../../../api' ; import { ErrorKind } from '../../../../../types' ; import alertDispatcher from '../../../../../utils/alertDispatcher' ; import UpdatePassword from './UpdatePassword' ; jest . mock ( '../../../../../api' ) ; jest . mock ( '../../../../../utils/alertDispatcher' ) ; describe ( 'Update password - user settings' , ( ) => { afterEach ( ( ) => { jest . resetAllMocks ( ) ; } ) ; it ( 'creates snapshot' , ( ) => { const { asFragment } = render ( < UpdatePassword />); expect ( asFragment ( ) ) . toMatchSnapshot ( ) ; } ) ; describe ( 'Render' , ( ) => { it ( 'renders component' , ( ) => { render ( < UpdatePassword />); const form = screen . getByTestId ( 'updatePasswordForm' ) ; expect ( form ) . toBeInTheDocument ( ) ; expect ( screen . getByTestId ( 'oldPasswordInput' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByTestId ( 'passwordInput' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByTestId ( 'confirmPasswordInput' ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'updates all fields and calls updatePassword' , async ( ) => { render ( < UpdatePassword />); const oldPassword = screen . getByTestId ( 'oldPasswordInput' ) as HTMLInputElement ; const newPassword = screen . getByTestId ( 'passwordInput' ) as HTMLInputElement ; const repeatNewPassword = screen . getByTestId ( 'confirmPasswordInput' ) as HTMLInputElement ; userEvent . type ( oldPassword , 'oldpass' ) ; userEvent . type ( newPassword , 'newpass' ) ; userEvent . type ( repeatNewPassword , 'newpass' ) ; const btn = screen . getByRole ( 'button' , { name : 'Update password' } ) ; expect ( btn ) . toBeInTheDocument ( ) ; userEvent . click ( btn ) ; await waitFor ( ( ) => { expect ( API . updatePassword ) . toBeCalledTimes ( 1 ) ; expect ( API . updatePassword ) . toHaveBeenCalledWith ( 'oldpass' , 'newpass' ) ; } ) ; } ) ; it ( 'escapes password properly' , async ( ) => { render ( < UpdatePassword />); const oldPassword = screen . getByTestId ( 'oldPasswordInput' ) as HTMLInputElement ; const newPassword = screen . getByTestId ( 'passwordInput' ) as HTMLInputElement ; const repeatNewPassword = screen . getByTestId ( 'confirmPasswordInput' ) as HTMLInputElement ; userEvent . type ( oldPassword , 'oldpass' ) ; userEvent . type ( newPassword , 'newpass$^' ) ; userEvent . type ( repeatNewPassword , 'newpass$^' ) ; const btn = screen . getByRole ( 'button' , { name : 'Update password' } ) ; expect ( btn ) . toBeInTheDocument ( ) ; userEvent . click ( btn ) ; await waitFor ( ( ) => { expect ( API . updatePassword ) . toBeCalledTimes ( 1 ) ; expect ( API . updatePassword ) . toHaveBeenCalledWith ( 'oldpass' , 'newpass$^' ) ; } ) ; } ) ; it ( "doesn`t pass form validation when passwords don't match" , async ( ) => { render ( < UpdatePassword />); const oldPassword = screen . getByTestId ( 'oldPasswordInput' ) as HTMLInputElement ; const newPassword = screen . getByTestId ( 'passwordInput' ) as HTMLInputElement ; const repeatNewPassword = screen . getByTestId ( 'confirmPasswordInput' ) as HTMLInputElement ; userEvent . type ( oldPassword , 'oldpass' ) ; userEvent . type ( newPassword , 'newpass' ) ; userEvent . type ( repeatNewPassword , 'noMatch' ) ; const btn = screen . getByRole ( 'button' , { name : 'Update password' } ) ; expect ( btn ) . toBeInTheDocument ( ) ; userEvent . click ( btn ) ; await waitFor ( ( ) => { expect ( API . updatePassword ) . toBeCalledTimes ( 0 ) ; } ) ; } ) ; } ) ; describe ( 'when updateUserProfile fails' , ( ) => { it ( 'with custom error message' , async ( ) => { mocked ( API ) . updatePassword . mockRejectedValue ( { kind : ErrorKind . Other , message : 'custom error' , } ) ; render ( < UpdatePassword />); userEvent . type ( screen . getByTestId ( 'oldPasswordInput' ) , 'oldpass' ) ; userEvent . type ( screen . getByTestId ( 'passwordInput' ) , 'newpass' ) ; userEvent . type ( screen . getByTestId ( 'confirmPasswordInput' ) , 'newpass' ) ; const btn = screen . getByRole ( 'button' , { name : 'Update password' } ) ; expect ( btn ) . toBeInTheDocument ( ) ; userEvent . click ( btn ) ; await waitFor ( ( ) => { expect ( API . updatePassword ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; expect ( alertDispatcher . postAlert ) . toHaveBeenCalledTimes ( 1 ) ; expect ( alertDispatcher . postAlert ) . toHaveBeenCalledWith ( { type : 'danger' , message : 'An error occurred updating your password: custom error' , } ) ; } ) ; it ( 'UnauthorizedError' , async ( ) => { mocked ( API ) . updatePassword . mockRejectedValue ( { kind : ErrorKind . Unauthorized , } ) ; render ( < UpdatePassword />); userEvent . type ( screen . getByTestId ( 'oldPasswordInput' ) , 'oldpass' ) ; userEvent . type ( screen . getByTestId ( 'passwordInput' ) , 'newpass' ) ; userEvent . type ( screen . getByTestId ( 'confirmPasswordInput' ) , 'newpass' ) ; const btn = screen . getByRole ( 'button' , { name : 'Update password' } ) ; expect ( btn ) . toBeInTheDocument ( ) ; userEvent . click ( btn ) ; await waitFor ( ( ) => { expect ( API . updatePassword ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; expect ( alertDispatcher . postAlert ) . toHaveBeenCalledTimes ( 1 ) ; expect ( alertDispatcher . postAlert ) . toHaveBeenCalledWith ( { type : 'danger' , message : 'An error occurred updating your password, please make sure you have entered your old password correctly' , } ) ; } ) ; it ( 'default error message' , async ( ) => { mocked ( API ) . updatePassword . mockRejectedValue ( { kind : ErrorKind . Other , } ) ; render ( < UpdatePassword />); userEvent . type ( screen . getByTestId ( 'oldPasswordInput' ) , 'oldpass' ) ; userEvent . type ( screen . getByTestId ( 'passwordInput' ) , 'newpass' ) ; userEvent . type ( screen . getByTestId ( 'confirmPasswordInput' ) , 'newpass' ) ; const btn = screen . getByRole ( 'button' , { name : 'Update password' } ) ; expect ( btn ) . toBeInTheDocument ( ) ; userEvent . click ( btn ) ; await waitFor ( ( ) => { expect ( API . updatePassword ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; expect ( alertDispatcher . postAlert ) . toHaveBeenCalledTimes ( 1 ) ; expect ( alertDispatcher . postAlert ) . toHaveBeenCalledWith ( { type : 'danger' , message : 'An error occurred updating your password, please try again later.' , } ) ; } ) ; } ) ; } ) ;