-
Notifications
You must be signed in to change notification settings - Fork 298
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Jim/wall 2947/unit tests for change password (#16659)
* chore: add testid to sent email content wrapper * chore: add unit tests for change password mt5 change password and trading platform change password * chore: add unit tests for investor password screens * chore: remove unused import * test: fix failing tests and update description * test: add more tests * test: refactor tests * chore: resolve sonarcloud issue
- Loading branch information
Showing
7 changed files
with
657 additions
and
1 deletion.
There are no files selected for viewing
173 changes: 173 additions & 0 deletions
173
.../ChangePassword/InvestorPassword/__tests__/MT5ChangeInvestorPasswordInputsScreen.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
import React, { PropsWithChildren } from 'react'; | ||
import { useTradingPlatformInvestorPasswordChange } from '@deriv/api-v2'; | ||
import { render, screen, waitFor } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { WalletButton } from '../../../../../../components/Base'; | ||
import { useModal } from '../../../../../../components/ModalProvider'; | ||
import useDevice from '../../../../../../hooks/useDevice'; | ||
import { validPasswordMT5 } from '../../../../../../utils/password-validation'; | ||
import MT5ChangeInvestorPasswordInputsScreen from '../MT5ChangeInvestorPasswordInputsScreen'; | ||
|
||
jest.mock('@deriv/api-v2', () => ({ | ||
useTradingPlatformInvestorPasswordChange: jest.fn(), | ||
})); | ||
|
||
jest.mock('../../../../../../components', () => ({ | ||
...jest.requireActual('../../../../../../components'), | ||
WalletsActionScreen: jest.fn(({ description, renderButtons }) => ( | ||
<div> | ||
{description} | ||
{renderButtons()} | ||
</div> | ||
)), | ||
})); | ||
|
||
jest.mock('../../../../../../components/Base', () => ({ | ||
...jest.requireActual('../../../../../../components/Base'), | ||
WalletButton: jest.fn( | ||
({ | ||
children, | ||
disabled, | ||
isLoading, | ||
onClick, | ||
type, | ||
}: PropsWithChildren<{ | ||
disabled: boolean; | ||
isLoading: boolean; | ||
onClick: () => void; | ||
textSize: string; | ||
type?: 'button' | 'reset' | 'submit'; | ||
}>) => { | ||
return ( | ||
<button disabled={disabled} onClick={onClick} type={type}> | ||
{isLoading && <>Loading...</>} | ||
{!isLoading ? children : null} | ||
</button> | ||
); | ||
} | ||
), | ||
})); | ||
|
||
jest.mock('../../../../../../components/ModalProvider', () => ({ | ||
...jest.requireActual('../../../../../../components/ModalProvider'), | ||
useModal: jest.fn(), | ||
})); | ||
|
||
jest.mock('../../../../../../components/Base/WalletPasswordField/PasswordViewerIcon', () => | ||
jest.fn(({ setViewPassword, viewPassword }) => ( | ||
<button onClick={() => setViewPassword(!viewPassword)}>PasswordViewerIcon</button> | ||
)) | ||
); | ||
|
||
jest.mock('../../../../../../hooks/useDevice', () => jest.fn()); | ||
|
||
jest.mock('../../../../../../utils/password-validation', () => ({ | ||
...jest.requireActual('../../../../../../utils/password-validation'), | ||
validPasswordMT5: jest.fn(), | ||
})); | ||
|
||
describe('MT5ChangeInvestorPasswordInputsScreen', () => { | ||
beforeEach(() => { | ||
(useTradingPlatformInvestorPasswordChange as jest.Mock).mockReturnValue({ | ||
mutateAsync: jest.fn(), | ||
status: 'idle', | ||
}); | ||
(useModal as jest.Mock).mockReturnValue({ | ||
getModalState: jest.fn().mockReturnValue('test-account-id'), | ||
}); | ||
(useDevice as jest.Mock).mockReturnValue({ | ||
isMobile: false, | ||
}); | ||
(validPasswordMT5 as jest.Mock).mockReturnValue(true); | ||
}); | ||
|
||
it('renders the component correctly', () => { | ||
render(<MT5ChangeInvestorPasswordInputsScreen />); | ||
|
||
expect(screen.getByText(/Use this password to grant viewing access to another user/)).toBeInTheDocument(); | ||
expect(screen.getByText(/Change investor password/)).toBeInTheDocument(); | ||
expect(screen.getByText(/Create or reset investor password/)).toBeInTheDocument(); | ||
}); | ||
|
||
it('validates current password field', async () => { | ||
render(<MT5ChangeInvestorPasswordInputsScreen />); | ||
|
||
userEvent.click(screen.getByText('Current investor password')); | ||
userEvent.tab(); | ||
userEvent.click(screen.getByText(/Change investor password/)); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByText('The field is required')).toBeInTheDocument(); | ||
}); | ||
}); | ||
|
||
it('submits the form with valid data', async () => { | ||
const newPassword = 'newPassword123'; | ||
const oldPassword = 'oldPassword123'; | ||
const mockChangePassword = jest.fn().mockResolvedValue({}); | ||
(useTradingPlatformInvestorPasswordChange as jest.Mock).mockReturnValue({ | ||
mutateAsync: mockChangePassword, | ||
}); | ||
|
||
render(<MT5ChangeInvestorPasswordInputsScreen setNextScreen={jest.fn()} />); | ||
|
||
userEvent.type(screen.getByLabelText(/Current investor password/), oldPassword); | ||
const newInvestorPasswordInput = await screen.findByText('New investor password'); | ||
userEvent.type(newInvestorPasswordInput, newPassword); | ||
|
||
userEvent.click(screen.getByText(/Change investor password/)); | ||
|
||
await waitFor(() => { | ||
expect(mockChangePassword).toHaveBeenCalledWith({ | ||
account_id: 'test-account-id', | ||
new_password: newPassword, | ||
old_password: oldPassword, | ||
platform: 'mt5', | ||
}); | ||
}); | ||
}); | ||
|
||
it('displays error message if change password fails', () => { | ||
(useTradingPlatformInvestorPasswordChange as jest.Mock).mockReturnValue({ | ||
error: { error: { message: 'Error changing password' } }, | ||
mutateAsync: jest.fn(), | ||
}); | ||
|
||
render(<MT5ChangeInvestorPasswordInputsScreen />); | ||
|
||
expect(screen.getByText('Error changing password')).toBeInTheDocument(); | ||
}); | ||
|
||
it('shows the loader when the change investor password mutation is loading', () => { | ||
(useTradingPlatformInvestorPasswordChange as jest.Mock).mockReturnValue({ | ||
status: 'loading', | ||
}); | ||
|
||
render(<MT5ChangeInvestorPasswordInputsScreen />); | ||
|
||
expect( | ||
screen.getByRole('button', { | ||
name: 'Loading...', | ||
}) | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
it('displays the password when the viewer icon is clicked', () => { | ||
render(<MT5ChangeInvestorPasswordInputsScreen />); | ||
|
||
const currentPasswordInput = screen.getByPlaceholderText('Current investor password'); | ||
expect(currentPasswordInput).toHaveAttribute('type', 'password'); | ||
|
||
userEvent.click(screen.getAllByRole('button', { name: 'PasswordViewerIcon' })[0]); | ||
|
||
expect(currentPasswordInput).toHaveAttribute('type', 'text'); | ||
}); | ||
|
||
it('renders button with correct text size for mobile', () => { | ||
(useDevice as jest.Mock).mockReturnValue({ isMobile: true }); | ||
|
||
render(<MT5ChangeInvestorPasswordInputsScreen />); | ||
|
||
expect(WalletButton).toHaveBeenCalledWith(expect.objectContaining({ textSize: 'md' }), {}); | ||
}); | ||
}); |
24 changes: 24 additions & 0 deletions
24
...s/ChangePassword/InvestorPassword/__tests__/MT5ChangeInvestorPasswordSavedScreen.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React from 'react'; | ||
import { render, screen } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import MT5ChangeInvestorPasswordSavedScreen from '../MT5ChangeInvestorPasswordSavedScreen'; | ||
|
||
describe('MT5ChangeInvestorPasswordSavedScreen', () => { | ||
it('renders without crashing', () => { | ||
render(<MT5ChangeInvestorPasswordSavedScreen />); | ||
|
||
expect(screen.getByText('Your investor password has been changed.')).toBeInTheDocument(); | ||
expect(screen.getByText('Password saved')).toBeInTheDocument(); | ||
expect(screen.getByRole('button', { name: /OK/i })).toBeInTheDocument(); | ||
}); | ||
|
||
it('calls setNextScreen when OK button is clicked', () => { | ||
const setNextScreenMock = jest.fn(); | ||
|
||
render(<MT5ChangeInvestorPasswordSavedScreen setNextScreen={setNextScreenMock} />); | ||
|
||
userEvent.click(screen.getByRole('button', { name: /OK/i })); | ||
|
||
expect(setNextScreenMock).toHaveBeenCalled(); | ||
}); | ||
}); |
88 changes: 88 additions & 0 deletions
88
...reens/ChangePassword/InvestorPassword/__tests__/MT5ChangeInvestorPasswordScreens.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import React from 'react'; | ||
import { useActiveWalletAccount, useSettings, useVerifyEmail } from '@deriv/api-v2'; | ||
import { render, screen, waitFor } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { useModal } from '../../../../../../components/ModalProvider'; | ||
import MT5ChangeInvestorPasswordScreens from '../MT5ChangeInvestorPasswordScreens'; | ||
|
||
jest.mock('@deriv/api-v2', () => ({ | ||
...jest.requireActual('@deriv/api-v2'), | ||
useActiveWalletAccount: jest.fn(), | ||
useSettings: jest.fn(), | ||
useVerifyEmail: jest.fn(), | ||
})); | ||
|
||
jest.mock('../../../../../../components/ModalProvider', () => ({ | ||
...jest.requireActual('../../../../../../components/ModalProvider'), | ||
useModal: jest.fn(), | ||
})); | ||
|
||
jest.mock('../MT5ChangeInvestorPasswordInputsScreen', () => | ||
jest.fn(({ sendEmail, setNextScreen }) => ( | ||
<div> | ||
<button onClick={sendEmail}>Send Email</button> | ||
<button onClick={setNextScreen}>Next Screen</button> | ||
</div> | ||
)) | ||
); | ||
|
||
jest.mock('../MT5ChangeInvestorPasswordSavedScreen', () => | ||
jest.fn(({ setNextScreen }) => ( | ||
<div> | ||
<button onClick={setNextScreen}>Close</button> | ||
</div> | ||
)) | ||
); | ||
|
||
describe('MT5ChangeInvestorPasswordScreens', () => { | ||
beforeEach(() => { | ||
(useModal as jest.Mock).mockReturnValue({ | ||
getModalState: jest.fn().mockReturnValue('account-id'), | ||
hide: jest.fn(), | ||
}); | ||
(useSettings as jest.Mock).mockReturnValue({ data: { email: 'user@example.com' } }); | ||
(useVerifyEmail as jest.Mock).mockReturnValue({ mutate: jest.fn() }); | ||
(useActiveWalletAccount as jest.Mock).mockReturnValue({ data: { is_virtual: false } }); | ||
}); | ||
|
||
it('renders intro screen by default', () => { | ||
render(<MT5ChangeInvestorPasswordScreens />); | ||
|
||
expect(screen.getByRole('button', { name: 'Send Email' })).toBeInTheDocument(); | ||
expect(screen.getByRole('button', { name: 'Next Screen' })).toBeInTheDocument(); | ||
}); | ||
|
||
it('handles send email button click', async () => { | ||
const setShowEmailSentScreen = jest.fn(); | ||
const { mutate } = useVerifyEmail(); | ||
|
||
render(<MT5ChangeInvestorPasswordScreens setShowEmailSentScreen={setShowEmailSentScreen} />); | ||
|
||
userEvent.click(screen.getByRole('button', { name: 'Send Email' })); | ||
|
||
await waitFor(() => { | ||
expect(mutate).toHaveBeenCalled(); | ||
expect(setShowEmailSentScreen).toHaveBeenCalledWith(true); | ||
expect(localStorage.getItem('trading_platform_investor_password_reset_account_id')).toBe('account-id'); | ||
}); | ||
}); | ||
|
||
it('switches to saved screen on next screen button click', () => { | ||
render(<MT5ChangeInvestorPasswordScreens />); | ||
|
||
userEvent.click(screen.getByRole('button', { name: 'Next Screen' })); | ||
|
||
expect(screen.getByRole('button', { name: 'Close' })).toBeInTheDocument(); | ||
}); | ||
|
||
it('calls hide modal on close button click in saved screen', () => { | ||
const { hide } = useModal(); | ||
|
||
render(<MT5ChangeInvestorPasswordScreens />); | ||
|
||
userEvent.click(screen.getByRole('button', { name: 'Next Screen' })); | ||
userEvent.click(screen.getByRole('button', { name: 'Close' })); | ||
|
||
expect(hide).toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.