From 2fc317b2142ea96aa00af24097a8b3ada2dd3504 Mon Sep 17 00:00:00 2001 From: lubega-deriv <142860499+lubega-deriv@users.noreply.github.com> Date: Wed, 13 Mar 2024 18:30:29 +0800 Subject: [PATCH] chore: withdrawal crypto disclaimer and receipt unit tests (#14123) --- .../Base/WalletClipboard/WalletClipboard.tsx | 4 +- .../WithdrawalCryptoDisclaimer.tsx | 4 +- .../WithdrawalCryptoDisclaimer.spec.tsx | 14 ++ .../WithdrawalCryptoAmountConverter.tsx | 3 + .../WithdrawalCryptoAmountConverter.spec.tsx | 168 ++++++++++++++++++ .../WithdrawalCryptoReceipt.spec.tsx | 68 +++++++ .../WithdrawalCryptoDestinationAddress.tsx | 9 +- ...ithdrawalCryptoDestinationAddress.spec.tsx | 20 +++ 8 files changed, 278 insertions(+), 12 deletions(-) create mode 100644 packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoDisclaimer/__tests__/WithdrawalCryptoDisclaimer.spec.tsx create mode 100644 packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoForm/components/WithdrawalCryptoAmountConverter/__tests__/WithdrawalCryptoAmountConverter.spec.tsx create mode 100644 packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/__tests__/WithdrawalCryptoReceipt.spec.tsx create mode 100644 packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/components/WithdrawalCryptoDestinationAddress/__tests__/WithdrawalCryptoDestinationAddress.spec.tsx diff --git a/packages/wallets/src/components/Base/WalletClipboard/WalletClipboard.tsx b/packages/wallets/src/components/Base/WalletClipboard/WalletClipboard.tsx index f2e64f07e109..69f025352454 100644 --- a/packages/wallets/src/components/Base/WalletClipboard/WalletClipboard.tsx +++ b/packages/wallets/src/components/Base/WalletClipboard/WalletClipboard.tsx @@ -8,8 +8,8 @@ import './WalletClipboard.scss'; type TProps = { infoMessage?: string; - popoverAlignment: 'bottom' | 'left' | 'right' | 'top'; - successMessage: string; + popoverAlignment?: 'bottom' | 'left' | 'right' | 'top'; + successMessage?: string; textCopy: string; }; diff --git a/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoDisclaimer/WithdrawalCryptoDisclaimer.tsx b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoDisclaimer/WithdrawalCryptoDisclaimer.tsx index dbef77fca77a..9a11913d8851 100644 --- a/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoDisclaimer/WithdrawalCryptoDisclaimer.tsx +++ b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoDisclaimer/WithdrawalCryptoDisclaimer.tsx @@ -11,8 +11,8 @@ const WithdrawalDisclaimer = () => ( the initial coin offering (ICO) tokens will not be credited into your account.
  • - Please note that your maximum and minimum withdrawal limits aren’t fixed. They change due to the - high volatility of cryptocurrency. + Please note that your maximum and minimum withdrawal limits aren't fixed. They change due to + the high volatility of cryptocurrency.
  • diff --git a/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoDisclaimer/__tests__/WithdrawalCryptoDisclaimer.spec.tsx b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoDisclaimer/__tests__/WithdrawalCryptoDisclaimer.spec.tsx new file mode 100644 index 000000000000..08f5b57a6602 --- /dev/null +++ b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoDisclaimer/__tests__/WithdrawalCryptoDisclaimer.spec.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import WithdrawalCryptoDisclaimer from '../WithdrawalCryptoDisclaimer'; + +describe('WithdrawalCryptoDisclaimer', () => { + it('should render content of withdrawal crypto disclaimer', () => { + render(); + + expect(screen.getByText(/Do not enter an address linked to an initial coin offering/)).toBeInTheDocument(); + expect( + screen.getByText(/Please note that your maximum and minimum withdrawal limits aren't fixed./) + ).toBeInTheDocument(); + }); +}); diff --git a/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoForm/components/WithdrawalCryptoAmountConverter/WithdrawalCryptoAmountConverter.tsx b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoForm/components/WithdrawalCryptoAmountConverter/WithdrawalCryptoAmountConverter.tsx index bdad9a8a07e9..094c0bcf39fb 100644 --- a/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoForm/components/WithdrawalCryptoAmountConverter/WithdrawalCryptoAmountConverter.tsx +++ b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoForm/components/WithdrawalCryptoAmountConverter/WithdrawalCryptoAmountConverter.tsx @@ -68,6 +68,7 @@ const WithdrawalCryptoAmountConverter: React.FC = () => { {({ field }: FieldProps) => ( { className={classNames('wallets-withdrawal-crypto-amount-converter__arrow', { 'wallets-withdrawal-crypto-amount-converter__arrow--rtl': !isCryptoInputActive, })} + data-testid='dt_withdrawal_crypto_amount_converter_arrow' > @@ -88,6 +90,7 @@ const WithdrawalCryptoAmountConverter: React.FC = () => { {({ field }: FieldProps) => ( ({ + ...jest.requireActual('../../../../../utils'), + validateCryptoInput: jest.fn(), + validateFiatInput: jest.fn(), +})); + +jest.mock('../../../../../provider', () => ({ + ...jest.requireActual('../../../../../provider'), + useWithdrawalCryptoContext: jest.fn(), +})); + +const mockUseWithdrawalCryptoContext = useWithdrawalCryptoContext as jest.MockedFunction< + typeof useWithdrawalCryptoContext +>; +const mockValidateCryptoInput = validateCryptoInput as jest.Mock; +const mockValidateFiatInput = validateFiatInput as jest.Mock; + +const wrapper: React.FC = ({ children }) => { + return ( + + {children} + + ); +}; + +describe('WithdrawalCryptoAmountConverter', () => { + beforeEach(() => { + mockUseWithdrawalCryptoContext.mockReturnValue({ + accountLimits: { + remainder: undefined, + }, + // @ts-expect-error - since this is a mock, we only need partial properties of the hook + activeAccount: { + currency: 'BTC', + }, + fractionalDigits: { + crypto: 8, + fiat: 2, + }, + getConvertedCryptoAmount: (fiatInput: number | string) => fiatInput as string, + getConvertedFiatAmount: (cryptoInput: number | string) => cryptoInput as string, + isClientVerified: false, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should display error below crypto input field if crypto input is invalid', async () => { + mockValidateCryptoInput.mockReturnValue('Crypto Input Error'); + + render(, { wrapper }); + + const cryptoInput = screen.getByTestId('dt_withdrawal_crypto_amount_input'); + + await act(async () => { + await fireEvent.change(cryptoInput, { target: { value: '10' } }); + }); + expect(screen.getByText('Crypto Input Error')).toBeInTheDocument(); + }); + + it('should change value of fiat input field when value of crypto input changes', async () => { + mockValidateCryptoInput.mockReturnValue(''); + + render(, { wrapper }); + + const cryptoInput = screen.getByTestId('dt_withdrawal_crypto_amount_input'); + const fiatInput = screen.getByTestId('dt_withdrawal_fiat_amount_input'); + await act(async () => { + await fireEvent.change(cryptoInput, { target: { value: '10' } }); + }); + expect(fiatInput).toHaveValue('10'); + }); + + it('should empty fiat input field if crypto input field has errors', async () => { + mockValidateCryptoInput.mockReturnValue('Crypto Input Error'); + + render(, { wrapper }); + + const cryptoInput = screen.getByTestId('dt_withdrawal_crypto_amount_input'); + const fiatInput = screen.getByTestId('dt_withdrawal_fiat_amount_input'); + await act(async () => { + await fireEvent.change(cryptoInput, { target: { value: '10' } }); + }); + expect(fiatInput).toHaveValue(''); + }); + + it('should display error below fiat input field if fiat input is invalid', async () => { + mockValidateFiatInput.mockReturnValue('Fiat Input Error'); + + render(, { wrapper }); + + const fiatInput = screen.getByTestId('dt_withdrawal_fiat_amount_input'); + + await act(async () => { + await fireEvent.change(fiatInput, { target: { value: '10' } }); + }); + expect(screen.getByText('Fiat Input Error')).toBeInTheDocument(); + }); + + it('should change value of crypto input field when value of fiat input changes', async () => { + mockValidateFiatInput.mockReturnValue(''); + + render(, { wrapper }); + + const cryptoInput = screen.getByTestId('dt_withdrawal_crypto_amount_input'); + const fiatInput = screen.getByTestId('dt_withdrawal_fiat_amount_input'); + await act(async () => { + await fireEvent.change(fiatInput, { target: { value: '10' } }); + }); + expect(cryptoInput).toHaveValue('10'); + }); + + it('should empty crypto input field if fiat input field has errors', async () => { + mockValidateFiatInput.mockReturnValue('Fiat Input Error'); + + render(, { wrapper }); + + const cryptoInput = screen.getByTestId('dt_withdrawal_crypto_amount_input'); + const fiatInput = screen.getByTestId('dt_withdrawal_fiat_amount_input'); + await act(async () => { + await fireEvent.change(fiatInput, { target: { value: '10' } }); + }); + expect(cryptoInput).toHaveValue(''); + }); + + it('should handle onFocus for crypto input field', async () => { + render(, { wrapper }); + + const cryptoInput = screen.getByTestId('dt_withdrawal_crypto_amount_input'); + await act(async () => { + await fireEvent.focus(cryptoInput); + }); + + expect(screen.queryByTestId('dt_withdrawal_crypto_amount_converter_arrow')).not.toHaveClass( + 'wallets-withdrawal-crypto-amount-converter__arrow--rtl' + ); + }); + + it('should handle onFocus for fiat input field', async () => { + render(, { wrapper }); + + const fiatInput = screen.getByTestId('dt_withdrawal_fiat_amount_input'); + await act(async () => { + await fireEvent.focus(fiatInput); + }); + + expect(screen.getByTestId('dt_withdrawal_crypto_amount_converter_arrow')).toHaveClass( + 'wallets-withdrawal-crypto-amount-converter__arrow--rtl' + ); + }); +}); diff --git a/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/__tests__/WithdrawalCryptoReceipt.spec.tsx b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/__tests__/WithdrawalCryptoReceipt.spec.tsx new file mode 100644 index 000000000000..6fa930ba085b --- /dev/null +++ b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/__tests__/WithdrawalCryptoReceipt.spec.tsx @@ -0,0 +1,68 @@ +import React, { PropsWithChildren } from 'react'; +import { APIProvider, AuthProvider } from '@deriv/api-v2'; +import { fireEvent, render, screen } from '@testing-library/react'; +import WithdrawalCryptoReceipt from '../WithdrawalCryptoReceipt'; + +const mockPush = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useHistory: jest.fn(() => ({ + push: mockPush, + })), +})); + +const mockWithdrawalReceipt = { + address: 'test_crypto_address', +}; + +const wrapper = ({ children }: PropsWithChildren) => ( + + {children} + +); + +describe('WithdrawalCryptoReceipt', () => { + it('should render the component with withdrawal information', () => { + const mockBTCWithdrawalReceipt = { + address: 'test_crypto_address', + amount: '100', + currency: 'BTC', + }; + render( jest.fn()} withdrawalReceipt={mockBTCWithdrawalReceipt} />, { + wrapper, + }); + + const amountElement = screen.getByText('100 BTC'); + expect(amountElement).toBeInTheDocument(); + + const addressElement = screen.getByText('test_crypto_address'); + expect(addressElement).toBeInTheDocument(); + + const reviewTextElement = screen.getByText( + 'Your withdrawal is currently in review. It will be processed within 24 hours. We’ll send you an email once your transaction has been processed.' + ); + expect(reviewTextElement).toBeInTheDocument(); + }); + + it('should trigger the close function when the "Close" button is clicked', () => { + const onCloseMock = jest.fn(); + + render(, { + wrapper, + }); + + fireEvent.click(screen.getByText('Close')); + + expect(onCloseMock).toHaveBeenCalled(); + }); + + it('should navigate to the transactions page when the "View transactions" button is clicked', () => { + render( jest.fn()} withdrawalReceipt={mockWithdrawalReceipt} />, { + wrapper, + }); + + fireEvent.click(screen.getByText('View transactions')); + + expect(mockPush).toHaveBeenCalledWith('/wallets/cashier/transactions'); + }); +}); diff --git a/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/components/WithdrawalCryptoDestinationAddress/WithdrawalCryptoDestinationAddress.tsx b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/components/WithdrawalCryptoDestinationAddress/WithdrawalCryptoDestinationAddress.tsx index 90ead3ec4fba..7a1770088a2b 100644 --- a/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/components/WithdrawalCryptoDestinationAddress/WithdrawalCryptoDestinationAddress.tsx +++ b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/components/WithdrawalCryptoDestinationAddress/WithdrawalCryptoDestinationAddress.tsx @@ -1,10 +1,8 @@ import React from 'react'; import { WalletClipboard, WalletText } from '../../../../../../../../components'; -import useDevice from '../../../../../../../../hooks/useDevice'; import './WithdrawalCryptoDestinationAddress.scss'; const WithdrawalCryptoDestinationAddress: React.FC<{ address?: string }> = ({ address }) => { - const { isMobile } = useDevice(); return (
    @@ -16,12 +14,7 @@ const WithdrawalCryptoDestinationAddress: React.FC<{ address?: string }> = ({ ad {address} - +
    ); diff --git a/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/components/WithdrawalCryptoDestinationAddress/__tests__/WithdrawalCryptoDestinationAddress.spec.tsx b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/components/WithdrawalCryptoDestinationAddress/__tests__/WithdrawalCryptoDestinationAddress.spec.tsx new file mode 100644 index 000000000000..d81b49a792b5 --- /dev/null +++ b/packages/wallets/src/features/cashier/modules/WithdrawalCrypto/components/WithdrawalCryptoReceipt/components/WithdrawalCryptoDestinationAddress/__tests__/WithdrawalCryptoDestinationAddress.spec.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import WithdrawalCryptoDestinationAddress from '../WithdrawalCryptoDestinationAddress'; + +describe('WithdrawalCryptoDestinationAddress', () => { + it('should render the component with the provided address', () => { + const address = 'your_crypto_address'; + render(); + + const addressElement = screen.getByText(address); + expect(addressElement).toBeInTheDocument(); + }); + + it('should render the component without an address', () => { + render(); + + const noAddressElement = screen.getByText('Destination address'); + expect(noAddressElement).toBeInTheDocument(); + }); +});