Skip to content

Commit

Permalink
[WALL] Lubega / WALL-3517 / Withdrawal locked currency config load (b…
Browse files Browse the repository at this point in the history
…inary-com#13918)

* fix: withdrawal limit reached currency config

* fix: updated useCurrencyConfig isLoading

* fix: updated unit tests

* fix: applied comments
  • Loading branch information
lubega-deriv committed Feb 29, 2024
1 parent 346b32c commit fc2b538
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 112 deletions.
9 changes: 7 additions & 2 deletions packages/api-v2/src/hooks/useCurrencyConfig.ts
Expand Up @@ -5,12 +5,16 @@ import useAuthorize from './useAuthorize';
/** A custom hook to get the currency config information from `website_status` endpoint and `crypto_config` endpoint. */
const useCurrencyConfig = () => {
const { isSuccess } = useAuthorize();
const { data: website_status_data, ...rest } = useQuery('website_status', {
const {
data: website_status_data,
isLoading: isWebsiteStatusLoading,
...rest
} = useQuery('website_status', {
options: {
enabled: isSuccess,
},
});
const { data: crypto_config_data } = useQuery('crypto_config', {
const { data: crypto_config_data, isLoading: isCryptConfigLoading } = useQuery('crypto_config', {
options: {
enabled: isSuccess,
},
Expand Down Expand Up @@ -103,6 +107,7 @@ const useCurrencyConfig = () => {
data: transformed_currencies_config,
/** Returns the currency config object for the given currency */
getConfig,
isLoading: isWebsiteStatusLoading || isCryptConfigLoading,
...rest,
};
};
Expand Down
Expand Up @@ -6,9 +6,10 @@ import {
useActiveWalletAccount,
useAuthentication,
useCashierValidation,
useCurrencyConfig,
} from '@deriv/api-v2';
import { WalletsActionScreen } from '../../../../components';
import getWithdrawalLockedDesc from './WithdrawalLockedContent';
import { Loader, WalletsActionScreen } from '../../../../components';
import getWithdrawalLockedDesc, { getWithdrawalLimitReachedDesc } from './WithdrawalLockedContent';
import './WithdrawalLocked.scss';

const WithdrawalLocked: React.FC<React.PropsWithChildren> = ({ children }) => {
Expand All @@ -17,6 +18,7 @@ const WithdrawalLocked: React.FC<React.PropsWithChildren> = ({ children }) => {
const { data: cashierValidation } = useCashierValidation();
const { data: accountLimits } = useAccountLimits();
const { data: status } = useAccountStatus();
const { isLoading: isCurrencyConfigLoading } = useCurrencyConfig();

const currency = activeWallet?.currency || 'USD';

Expand All @@ -35,29 +37,53 @@ const WithdrawalLocked: React.FC<React.PropsWithChildren> = ({ children }) => {
const isWithdrawalLocked = status?.is_withdrawal_locked;

const remainder = accountLimits?.remainder;
const minimumWithdrawal = activeWallet?.currency_config?.minimum_withdrawal;
const minimumWithdrawal = activeWallet?.currency_config?.is_crypto
? activeWallet?.currency_config?.minimum_withdrawal
: 0.01;
const withdrawalLimitReached = !!(
typeof remainder !== 'undefined' &&
typeof minimumWithdrawal !== 'undefined' &&
+remainder < minimumWithdrawal
);

if (isCurrencyConfigLoading) {
return <Loader />;
}

if (withdrawalLimitReached) {
return (
<div className='wallets-withdrawal-locked'>
<WalletsActionScreen
description={
getWithdrawalLimitReachedDesc({
askFinancialRiskApproval,
poaNeedsVerification,
poaStatus,
poiNeedsVerification,
poiStatus,
})?.description
}
title={
<Trans
defaults='Withdrawals from your {{currency}} Wallet are temporarily locked.'
values={{ currency }}
/>
}
/>
</div>
);
}

if (isWithdrawalLocked) {
return (
<div className='wallets-withdrawal-locked'>
<WalletsActionScreen
description={
getWithdrawalLockedDesc({
askAuthenticate,
askFinancialRiskApproval,
askFixDetails,
financialAssessmentRequired,
noWithdrawalOrTradingStatus,
poaNeedsVerification,
poaStatus,
poiNeedsVerification,
poiStatus,
withdrawalLimitReached,
withdrawalLockedStatus,
})?.description
}
Expand Down
Expand Up @@ -2,34 +2,30 @@ import React from 'react';
import { Trans } from 'react-i18next';
import { WalletLink, WalletText } from '../../../../components';

type TWithdrawalLockedDescProps = {
askAuthenticate?: boolean;
type TWithdrawalLimitReachedDescProps = {
askFinancialRiskApproval?: boolean;
askFixDetails?: boolean;
financialAssessmentRequired?: boolean;
noWithdrawalOrTradingStatus?: boolean;
poaNeedsVerification?: boolean;
poaStatus: string;
poiNeedsVerification?: boolean;
poiStatus: string;
withdrawalLimitReached: boolean;
};

type TWithdrawalLockedDescProps = {
askAuthenticate?: boolean;
askFixDetails?: boolean;
financialAssessmentRequired?: boolean;
noWithdrawalOrTradingStatus?: boolean;
withdrawalLockedStatus?: boolean;
};

const getWithdrawalLockedDesc = ({
askAuthenticate,
export const getWithdrawalLimitReachedDesc = ({
askFinancialRiskApproval,
askFixDetails,
financialAssessmentRequired,
noWithdrawalOrTradingStatus,
poaNeedsVerification,
poaStatus,
poiNeedsVerification,
poiStatus,
withdrawalLimitReached,
withdrawalLockedStatus,
}: TWithdrawalLockedDescProps) => {
if (withdrawalLimitReached && poiNeedsVerification && poiStatus === 'none')
}: TWithdrawalLimitReachedDescProps) => {
if (poiNeedsVerification && poiStatus === 'none')
return {
description: (
<WalletText align='center'>
Expand All @@ -41,7 +37,7 @@ const getWithdrawalLockedDesc = ({
),
};

if (withdrawalLimitReached && poiNeedsVerification && poiStatus !== 'verified' && poiStatus !== 'none')
if (poiNeedsVerification && poiStatus !== 'verified' && poiStatus !== 'none')
return {
description: (
<WalletText align='center'>
Expand All @@ -53,7 +49,7 @@ const getWithdrawalLockedDesc = ({
),
};

if (withdrawalLimitReached && poaNeedsVerification && poaStatus === 'none')
if (poaNeedsVerification && poaStatus === 'none')
return {
description: (
<WalletText align='center'>
Expand All @@ -65,7 +61,7 @@ const getWithdrawalLockedDesc = ({
),
};

if (withdrawalLimitReached && poaNeedsVerification && poaStatus !== 'verified' && poaStatus !== 'none')
if (poaNeedsVerification && poaStatus !== 'verified' && poaStatus !== 'none')
return {
description: (
<WalletText align='center'>
Expand All @@ -77,7 +73,7 @@ const getWithdrawalLockedDesc = ({
),
};

if (withdrawalLimitReached && askFinancialRiskApproval)
if (askFinancialRiskApproval)
return {
description: (
<WalletText align='center'>
Expand All @@ -88,7 +84,15 @@ const getWithdrawalLockedDesc = ({
</WalletText>
),
};
};

const getWithdrawalLockedDesc = ({
askAuthenticate,
askFixDetails,
financialAssessmentRequired,
noWithdrawalOrTradingStatus,
withdrawalLockedStatus,
}: TWithdrawalLockedDescProps) => {
if (financialAssessmentRequired)
return {
description: (
Expand Down
Expand Up @@ -5,26 +5,32 @@ import {
useActiveWalletAccount,
useAuthentication,
useCashierValidation,
useCurrencyConfig,
} from '@deriv/api-v2';
import { render, screen } from '@testing-library/react';
import WithdrawalLocked from '../WithdrawalLocked';
import getWithdrawalLockedDesc from '../WithdrawalLockedContent';

jest.mock('@deriv/api-v2', () => ({
useAccountLimits: jest.fn(),
useAccountStatus: jest.fn(),
useActiveWalletAccount: jest.fn(),
useAuthentication: jest.fn(),
useCashierValidation: jest.fn(),
useCurrencyConfig: jest.fn(),
}));

jest.mock('../../../../../components', () => ({
...jest.requireActual('../../../../../components'),
Loader: jest.fn(() => <div>Loading...</div>),
}));

jest.mock('../WithdrawalLockedContent', () => ({
__esModule: true,
default: jest.fn(),
default: jest.fn(() => ({ description: <div>Locked Description</div> })),
getWithdrawalLimitReachedDesc: jest.fn(() => ({ description: <div>Locked Description</div> })),
}));

const mockActiveWalletData = { currency_config: { minimum_withdrawal: 10 } };
const mockAccountLimitsData = { remainder: 20 };
const mockActiveWalletData = { currency: 'USD', currency_config: { is_crypto: false, minimum_withdrawal: 10 } };
const mockAuthenticationData = {
is_poa_needed: false,
is_poi_needed: false,
Expand All @@ -37,24 +43,65 @@ const mockCashierValidationData = {
no_withdrawal_or_trading_status: false,
withdrawal_locked_status: false,
};
const mockStatusData = { is_withdrawal_locked: false };

describe('WithdrawalLocked', () => {
afterEach(() => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should render locked screen when in a locked state', () => {
it('should render loader when in a loading state', () => {
const mockStatusData = { is_withdrawal_locked: false };
const mockAccountLimitsData = { remainder: 20 };

(useActiveWalletAccount as jest.Mock).mockReturnValueOnce({ data: mockActiveWalletData });
(useAccountLimits as jest.Mock).mockReturnValueOnce({ data: mockAccountLimitsData });
(useAuthentication as jest.Mock).mockReturnValueOnce({ data: mockAuthenticationData });
(useCashierValidation as jest.Mock).mockReturnValueOnce({ data: mockCashierValidationData });
(useAccountStatus as jest.Mock).mockReturnValueOnce({ data: mockStatusData });
(useCurrencyConfig as jest.Mock).mockReturnValueOnce({ isLoading: true });

render(
<WithdrawalLocked>
<div>Test Child Component</div>
</WithdrawalLocked>
);

expect(screen.queryByText('Test Child Component')).not.toBeInTheDocument();
expect(screen.getByText('Loading...')).toBeInTheDocument();
});

it('should render locked screen for withdrawal locked when in a locked state', () => {
const mockLockedStatusData = { is_withdrawal_locked: true };
const mockAccountLimitsData = { remainder: 20 };

(useActiveWalletAccount as jest.Mock).mockReturnValueOnce({ data: mockActiveWalletData });
(useAccountLimits as jest.Mock).mockReturnValueOnce({ data: mockAccountLimitsData });
(useAuthentication as jest.Mock).mockReturnValueOnce({ data: mockAuthenticationData });
(useCashierValidation as jest.Mock).mockReturnValueOnce({ data: mockCashierValidationData });
(useAccountStatus as jest.Mock).mockReturnValueOnce({ data: mockLockedStatusData });
(useCurrencyConfig as jest.Mock).mockReturnValueOnce({ isLoading: false });

const mockLockedState = { description: 'Locked Description' };
(getWithdrawalLockedDesc as jest.Mock).mockReturnValueOnce(mockLockedState);
render(
<WithdrawalLocked>
<div>Test Child Component</div>
</WithdrawalLocked>
);

expect(screen.queryByText('Test Child Component')).not.toBeInTheDocument();
expect(screen.getByText('Locked Description')).toBeInTheDocument();
expect(screen.getByText('Withdrawals from your USD Wallet are temporarily locked.')).toBeInTheDocument();
});

it('should render locked screen for withdrawal limit reached when in a locked state', () => {
const mockStatusData = { is_withdrawal_locked: false };
const mockLockedAccountLimitsData = { remainder: 0 };

(useActiveWalletAccount as jest.Mock).mockReturnValueOnce({ data: mockActiveWalletData });
(useAccountLimits as jest.Mock).mockReturnValueOnce({ data: mockLockedAccountLimitsData });
(useAuthentication as jest.Mock).mockReturnValueOnce({ data: mockAuthenticationData });
(useCashierValidation as jest.Mock).mockReturnValueOnce({ data: mockCashierValidationData });
(useAccountStatus as jest.Mock).mockReturnValueOnce({ data: mockStatusData });
(useCurrencyConfig as jest.Mock).mockReturnValueOnce({ isLoading: false });

render(
<WithdrawalLocked>
Expand All @@ -68,13 +115,15 @@ describe('WithdrawalLocked', () => {
});

it('should render children when not in a locked state', () => {
const mockStatusData = { is_withdrawal_locked: false };
const mockAccountLimitsData = { remainder: 20 };

(useActiveWalletAccount as jest.Mock).mockReturnValueOnce({ data: mockActiveWalletData });
(useAccountLimits as jest.Mock).mockReturnValueOnce({ data: mockAccountLimitsData });
(useAuthentication as jest.Mock).mockReturnValueOnce({ data: mockAuthenticationData });
(useCashierValidation as jest.Mock).mockReturnValueOnce({ data: mockCashierValidationData });
(useAccountStatus as jest.Mock).mockReturnValueOnce({ data: mockStatusData });

(getWithdrawalLockedDesc as jest.Mock).mockReturnValueOnce(null);
(useCurrencyConfig as jest.Mock).mockReturnValueOnce({ isLoading: false });

render(
<WithdrawalLocked>
Expand Down

0 comments on commit fc2b538

Please sign in to comment.