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();
+ });
+});