From 465ec2f00daf36ee18c62a1af6033b513ce313ce Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Fri, 8 Nov 2024 10:41:51 +0800 Subject: [PATCH 01/13] chore: added new hook to get phone number verification, added PNV content in Verification --- .../AdvertsTableRow/AdvertsTableRow.tsx | 2 +- src/components/Checklist/Checklist.scss | 13 ++++- src/components/Checklist/Checklist.tsx | 56 +++++++++++++------ src/components/Verification/Verification.tsx | 23 +++++--- src/hooks/custom-hooks/index.ts | 1 + .../useGetPhoneNumberVerification.ts | 12 ++++ .../buy-sell/screens/BuySell/BuySell.tsx | 4 +- .../BuySell/__tests__/BuySell.spec.tsx | 6 +- .../__tests__/BuySellTable.spec.tsx | 2 +- 9 files changed, 86 insertions(+), 33 deletions(-) create mode 100644 src/hooks/custom-hooks/useGetPhoneNumberVerification.ts diff --git a/src/components/AdvertsTableRow/AdvertsTableRow.tsx b/src/components/AdvertsTableRow/AdvertsTableRow.tsx index 65b44fd7..5aa12806 100644 --- a/src/components/AdvertsTableRow/AdvertsTableRow.tsx +++ b/src/components/AdvertsTableRow/AdvertsTableRow.tsx @@ -91,7 +91,7 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => { const redirectToVerification = () => { const searchParams = new URLSearchParams(location.search); - searchParams.set('poi_poa_verified', 'false'); + searchParams.set('verified', 'false'); history.replace({ pathname: location.pathname, search: searchParams.toString(), diff --git a/src/components/Checklist/Checklist.scss b/src/components/Checklist/Checklist.scss index 5c08a41b..97ab14d9 100644 --- a/src/components/Checklist/Checklist.scss +++ b/src/components/Checklist/Checklist.scss @@ -41,6 +41,11 @@ cursor: not-allowed; } + &--done { + cursor: default; + background-color: #4bb4b3 !important; + } + &-icon { fill: #fff; } @@ -50,8 +55,14 @@ @include icon-wrapper; &-icon { - fill: #4bb4b3; + fill: #fff; } } + + &-text { + display: flex; + flex-direction: column; + width: 100%; + } } } diff --git a/src/components/Checklist/Checklist.tsx b/src/components/Checklist/Checklist.tsx index 3f6ae03b..ffad2897 100644 --- a/src/components/Checklist/Checklist.tsx +++ b/src/components/Checklist/Checklist.tsx @@ -1,3 +1,4 @@ +import clsx from 'clsx'; import { LabelPairedArrowRightLgBoldIcon, LabelPairedCheckMdBoldIcon } from '@deriv/quill-icons'; import { Button, Text, useDevice } from '@deriv-com/ui'; import './Checklist.scss'; @@ -5,6 +6,7 @@ import './Checklist.scss'; type TChecklistItem = { isDisabled?: boolean; onClick?: () => void; + phoneNumber?: string | null; status: string; testId?: string; text: string; @@ -12,32 +14,50 @@ type TChecklistItem = { const Checklist = ({ items }: { items: TChecklistItem[] }) => { const { isMobile } = useDevice(); + + const getTextColor = (isDisabled: boolean | undefined, status: string) => { + if (isDisabled) return 'less-prominent'; + if (status === 'rejected') return 'error'; + return 'general'; + }; + return (
- {items.map(item => ( -
- - {item.text} - - {item.status === 'done' ? ( -
- + {items.map(item => { + const isDone = item.status === 'done'; + + return ( +
+
+ + {item.text} + + {item.phoneNumber && ( + + {item.phoneNumber} + + )}
- ) : (
- ))} +
+ ); + })}
); }; diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index bb9dc55e..8c1f45d6 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -1,6 +1,6 @@ import { TLocalize } from 'types'; import { Checklist } from '@/components'; -import { usePoiPoaStatus } from '@/hooks/custom-hooks'; +import { useGetPhoneNumberVerification, usePoiPoaStatus } from '@/hooks/custom-hooks'; import { DerivLightIcCashierSendEmailIcon } from '@deriv/quill-icons'; import { Localize, useTranslations } from '@deriv-com/translations'; import { Loader, Text, useDevice } from '@deriv-com/ui'; @@ -14,9 +14,9 @@ const getPoiAction = (status: string | undefined, localize: TLocalize) => { case 'rejected': return localize('Identity verification failed. Please try again.'); case 'verified': - return localize('Identity verification complete.'); + return localize('Identity verified'); default: - return localize('Upload documents to verify your identity.'); + return localize('Your identity'); } }; @@ -32,15 +32,16 @@ const getPoaAction = ( return localize('Address verification failed. Please try again.'); case 'verified': if (isPoaAuthenticatedWithIdv) return localize('Upload documents to verify your address.'); - return localize('Address verification complete.'); + return localize('Address verified'); default: - return localize('Upload documents to verify your address.'); + return localize('Your address'); } }; const Verification = () => { const { isMobile } = useDevice(); const { localize } = useTranslations(); + const { isPhoneNumberVerified, phoneNumber } = useGetPhoneNumberVerification(); const { data, isLoading } = usePoiPoaStatus(); const { isP2PPoaRequired, @@ -69,6 +70,14 @@ const Verification = () => { }; const checklistItems = [ + { + onClick: () => { + window.location.href = `${URLConstants.derivAppProduction}/account/personal-details`; + }, + phoneNumber: isPhoneNumberVerified ? phoneNumber : undefined, + status: isPhoneNumberVerified ? 'done' : 'action', + text: isPhoneNumberVerified ? localize('Phone number verified') : localize('Your phone number'), + }, { isDisabled: isPoiPending, onClick: () => { @@ -101,10 +110,10 @@ const Verification = () => {
- + - +
diff --git a/src/hooks/custom-hooks/index.ts b/src/hooks/custom-hooks/index.ts index 5a8d9d85..562636ff 100644 --- a/src/hooks/custom-hooks/index.ts +++ b/src/hooks/custom-hooks/index.ts @@ -8,6 +8,7 @@ export { default as useFetchMore } from './useFetchMore'; export { default as useFloatingRate } from './useFloatingRate'; export { default as useFullScreen } from './useFullScreen'; export { default as useGetBusinessHours } from './useGetBusinessHours.tsx'; +export { default as useGetPhoneNumberVerification } from './useGetPhoneNumberVerification'; export { default as useGrowthbookGetFeatureValue } from './useGrowthbookGetFeatureValue'; export { default as useHandleRouteChange } from './useHandleRouteChange'; export { default as useIsAdvertiser } from './useIsAdvertiser'; diff --git a/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts b/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts new file mode 100644 index 00000000..b861a049 --- /dev/null +++ b/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts @@ -0,0 +1,12 @@ +import { useGetSettings } from '@deriv-com/api-hooks'; + +/** A custom hook that returns if the user's phone number is verified and the phone number */ +const useGetPhoneNumberVerification = () => { + const { data } = useGetSettings(); + const isPhoneNumberVerified = !!data?.phone_number_verification?.verified; + const phoneNumber = data?.phone; + + return { isPhoneNumberVerified, phoneNumber }; +}; + +export default useGetPhoneNumberVerification; diff --git a/src/pages/buy-sell/screens/BuySell/BuySell.tsx b/src/pages/buy-sell/screens/BuySell/BuySell.tsx index 509dac76..6c416ff9 100644 --- a/src/pages/buy-sell/screens/BuySell/BuySell.tsx +++ b/src/pages/buy-sell/screens/BuySell/BuySell.tsx @@ -13,9 +13,9 @@ const BuySell = () => { const isAdvertiserBarred = useIsAdvertiserBarred(); const history = useHistory(); const location = useLocation(); - const poiPoaVerified = new URLSearchParams(location.search).get('poi_poa_verified'); + const verified = new URLSearchParams(location.search).get('verified'); - if (poiPoaVerified === 'false') { + if (verified === 'false') { return (
', () => { expect(screen.getByText('BuySellTable')).toBeInTheDocument(); }); - it('should render the PageReturn and Verification components if poi_poa_verified search param is false', () => { + it('should render the PageReturn and Verification components if verified search param is false', () => { (mockUseLocation as jest.Mock).mockImplementation(() => ({ - search: '?poi_poa_verified=false', + search: '?verified=false', })); render(); @@ -81,7 +81,7 @@ describe('', () => { it('should call history.replace when PageReturn is clicked', async () => { (mockUseLocation as jest.Mock).mockImplementation(() => ({ - search: '?poi_poa_verified=false', + search: '?verified=false', })); render(); diff --git a/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx b/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx index 5aadb98a..f957c2e2 100644 --- a/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx +++ b/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx @@ -246,7 +246,7 @@ describe('', () => { expect(mockUseHistory.replace).toHaveBeenCalledWith({ pathname: '/buy-sell', - search: 'poi_poa_verified=false', + search: 'verified=false', }); }); From 490ea07c8c4df391321fb43b72750991d77bb6b3 Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Fri, 8 Nov 2024 11:28:53 +0800 Subject: [PATCH 02/13] chore: updated Verification test cases --- src/components/Verification/Verification.tsx | 11 ++- .../__tests__/Verification.spec.tsx | 85 ++++++++++++++----- .../useGetPhoneNumberVerification.spec.ts | 30 +++++++ 3 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index 8c1f45d6..e4a4121d 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -38,6 +38,12 @@ const getPoaAction = ( } }; +const getStatus = (status: string | undefined) => { + if (status === 'verified') return 'done'; + else if (status === 'rejected') return 'rejected'; + return 'action'; +}; + const Verification = () => { const { isMobile } = useDevice(); const { localize } = useTranslations(); @@ -76,6 +82,7 @@ const Verification = () => { }, phoneNumber: isPhoneNumberVerified ? phoneNumber : undefined, status: isPhoneNumberVerified ? 'done' : 'action', + testId: 'dt_verification_phone_number_arrow_button', text: isPhoneNumberVerified ? localize('Phone number verified') : localize('Your phone number'), }, { @@ -84,7 +91,7 @@ const Verification = () => { if (!isPoiVerified) redirectToVerification(`${URLConstants.derivAppProduction}/account/proof-of-identity`); }, - status: isPoiVerified ? 'done' : 'action', + status: getStatus(poiStatus), testId: 'dt_verification_poi_arrow_button', text: getPoiAction(poiStatus, localize), }, @@ -96,7 +103,7 @@ const Verification = () => { if (allowPoaRedirection) redirectToVerification(`${URLConstants.derivAppProduction}/account/proof-of-address`); }, - status: allowPoaRedirection ? 'action' : 'done', + status: getStatus(poaStatus), testId: 'dt_verification_poa_arrow_button', text: getPoaAction(isPoaAuthenticatedWithIdv, poaStatus, localize), }, diff --git a/src/components/Verification/__tests__/Verification.spec.tsx b/src/components/Verification/__tests__/Verification.spec.tsx index 6e547af5..c9fa07fc 100644 --- a/src/components/Verification/__tests__/Verification.spec.tsx +++ b/src/components/Verification/__tests__/Verification.spec.tsx @@ -1,10 +1,10 @@ -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { fireEvent, render, screen } from '@testing-library/react'; import Verification from '../Verification'; let mockUsePoiPoaStatusData = { data: { isP2PPoaRequired: 1, + isPoaAuthenticatedWithIdv: false, isPoaPending: false, isPoaVerified: false, isPoiPending: false, @@ -15,8 +15,14 @@ let mockUsePoiPoaStatusData = { isLoading: true, }; +let mockUseGetPhoneNumberVerificationData = { + isPhoneNumberVerified: false, + phoneNumber: '1234567890', +}; + jest.mock('@/hooks/custom-hooks', () => ({ ...jest.requireActual('@/hooks/custom-hooks'), + useGetPhoneNumberVerification: jest.fn(() => mockUseGetPhoneNumberVerificationData), usePoiPoaStatus: jest.fn(() => mockUsePoiPoaStatusData), })); @@ -49,17 +55,15 @@ describe('', () => { render(); - expect(screen.getByText('Verify your P2P account')).toBeInTheDocument(); - expect(screen.getByText('Verify your identity and address to use Deriv P2P.')).toBeInTheDocument(); - expect(screen.getByText('Upload documents to verify your identity.')).toBeInTheDocument(); - expect(screen.getByText('Upload documents to verify your address.')).toBeInTheDocument(); + expect(screen.getByText('Let’s get you secured')).toBeInTheDocument(); + expect(screen.getByText('Complete your P2P profile to enjoy secure transactions.')).toBeInTheDocument(); + expect(screen.getByText('Your phone number')).toBeInTheDocument(); + expect(screen.getByText('Your identity')).toBeInTheDocument(); + expect(screen.getByText('Your address')).toBeInTheDocument(); }); - it('should redirect user to proof-of-identity route if user clicks on arrow button', async () => { - mockUsePoiPoaStatusData = { - ...mockUsePoiPoaStatusData, - isLoading: false, - }; + it('should redirect user to account/personal-details route if user clicks on phone number arrow button', () => { + render(); Object.defineProperty(window, 'location', { value: { @@ -68,19 +72,33 @@ describe('', () => { writable: true, }); + const phoneNumberButton = screen.getByTestId('dt_verification_phone_number_arrow_button'); + expect(phoneNumberButton).toBeInTheDocument(); + + fireEvent.click(phoneNumberButton); + + expect(window.location.href).toBe('https://app.deriv.com/account/personal-details'); + }); + + it('should redirect user to proof-of-identity route if user clicks on arrow button', () => { + mockUsePoiPoaStatusData = { + ...mockUsePoiPoaStatusData, + isLoading: false, + }; + render(); const poiButton = screen.getByTestId('dt_verification_poi_arrow_button'); expect(poiButton).toBeInTheDocument(); - await userEvent.click(poiButton); + fireEvent.click(poiButton); expect(window.location.href).toBe( 'https://app.deriv.com/account/proof-of-identity?ext_platform_url=/cashier/p2p&platform=p2p-v2' ); }); - it('should redirect user to proof-of-address route if user clicks on arrow button', async () => { + it('should redirect user to proof-of-address route if user clicks on arrow button', () => { mockUsePoiPoaStatusData = { ...mockUsePoiPoaStatusData, isLoading: false, @@ -91,7 +109,7 @@ describe('', () => { const poaButton = screen.getByTestId('dt_verification_poa_arrow_button'); expect(poaButton).toBeInTheDocument(); - await userEvent.click(poaButton); + fireEvent.click(poaButton); expect(window.location.href).toBe( 'https://app.deriv.com/account/proof-of-address?ext_platform_url=/cashier/p2p&platform=p2p-v2' @@ -104,15 +122,17 @@ describe('', () => { isLoading: false, }; + window.location.search = 'param1=value1¶m2=value2'; + render(); const poiButton = screen.getByTestId('dt_verification_poi_arrow_button'); expect(poiButton).toBeInTheDocument(); - await userEvent.click(poiButton); + fireEvent.click(poiButton); expect(window.location.href).toBe( - 'https://app.deriv.com/account/proof-of-identity?ext_platform_url=/cashier/p2p&platform=p2p-v2' + 'https://app.deriv.com/account/proof-of-identity?ext_platform_url=/cashier/p2p&platform=p2p-v2¶m1=value1¶m2=value2' ); }); @@ -131,8 +151,8 @@ describe('', () => { render(); - const poaButton = screen.getAllByRole('button')[0]; - const poiButton = screen.getAllByRole('button')[1]; + const poaButton = screen.getAllByRole('button')[1]; + const poiButton = screen.getAllByRole('button')[2]; expect(screen.getByText('Identity verification in progress.')).toBeInTheDocument(); expect(screen.getByText('Address verification in progress.')).toBeInTheDocument(); @@ -145,6 +165,8 @@ describe('', () => { ...mockUsePoiPoaStatusData, data: { ...mockUsePoiPoaStatusData.data, + isPoaPending: false, + isPoiPending: false, poaStatus: 'rejected', poiStatus: 'rejected', }, @@ -157,6 +179,18 @@ describe('', () => { expect(screen.getByText('Address verification failed. Please try again.')).toBeInTheDocument(); }); + it('should show verified message and phone number if phone number is verified', () => { + mockUseGetPhoneNumberVerificationData = { + ...mockUseGetPhoneNumberVerificationData, + isPhoneNumberVerified: true, + }; + + render(); + + expect(screen.getByText('Phone number verified')).toBeInTheDocument(); + expect(screen.getByText('1234567890')).toBeInTheDocument(); + }); + it('should show verified message if poi/poa status is verified', () => { mockUsePoiPoaStatusData = { ...mockUsePoiPoaStatusData, @@ -170,7 +204,18 @@ describe('', () => { render(); - expect(screen.getByText('Identity verification complete.')).toBeInTheDocument(); - expect(screen.getByText('Address verification complete.')).toBeInTheDocument(); + expect(screen.getByText('Identity verified')).toBeInTheDocument(); + expect(screen.getByText('Address verified')).toBeInTheDocument(); + }); + + it('should should prompt user to upload documents if isPoaAuthenticatedWithIdv is true', () => { + mockUsePoiPoaStatusData = { + ...mockUsePoiPoaStatusData, + data: { ...mockUsePoiPoaStatusData.data, isPoaAuthenticatedWithIdv: true }, + }; + + render(); + + expect(screen.getByText('Upload documents to verify your address.')).toBeInTheDocument(); }); }); diff --git a/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts b/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts new file mode 100644 index 00000000..3bfd4bb6 --- /dev/null +++ b/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts @@ -0,0 +1,30 @@ +import { renderHook } from '@testing-library/react'; +import useGetPhoneNumberVerification from '../useGetPhoneNumberVerification'; + +const mockSettings = { + phone: '1234567890', + phone_number_verification: { + verified: 0, + }, +}; + +jest.mock('@deriv-com/api-hooks', () => ({ + useGetSettings: jest.fn(() => ({ data: mockSettings })), +})); + +describe('useGetPhoneNumberVerification', () => { + it('should return the phone number and false if the phone number is not verified', () => { + const { result } = renderHook(() => useGetPhoneNumberVerification()); + + expect(result.current.isPhoneNumberVerified).toBe(false); + expect(result.current.phoneNumber).toBe('1234567890'); + }); + + it('should return the phone number and true if the phone number is verified', () => { + mockSettings.phone_number_verification.verified = 1; + const { result } = renderHook(() => useGetPhoneNumberVerification()); + + expect(result.current.isPhoneNumberVerified).toBe(true); + expect(result.current.phoneNumber).toBe('1234567890'); + }); +}); From e032be0aad31ba6fc49eeccd9d38b6934ff3902b Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Fri, 8 Nov 2024 12:59:51 +0800 Subject: [PATCH 03/13] chore: added check if pnv is enabled in p2p_settings --- src/components/Verification/Verification.tsx | 24 +++++++++++-------- .../__tests__/Verification.spec.tsx | 12 +++++++++- .../api/settings/p2p-settings/useSettings.ts | 2 ++ .../useGetPhoneNumberVerification.spec.ts | 17 +++++++++++-- .../useGetPhoneNumberVerification.ts | 6 ++++- 5 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index e4a4121d..8b9b3c1b 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -47,7 +47,7 @@ const getStatus = (status: string | undefined) => { const Verification = () => { const { isMobile } = useDevice(); const { localize } = useTranslations(); - const { isPhoneNumberVerified, phoneNumber } = useGetPhoneNumberVerification(); + const { isPhoneNumberVerificationEnabled, isPhoneNumberVerified, phoneNumber } = useGetPhoneNumberVerification(); const { data, isLoading } = usePoiPoaStatus(); const { isP2PPoaRequired, @@ -76,15 +76,19 @@ const Verification = () => { }; const checklistItems = [ - { - onClick: () => { - window.location.href = `${URLConstants.derivAppProduction}/account/personal-details`; - }, - phoneNumber: isPhoneNumberVerified ? phoneNumber : undefined, - status: isPhoneNumberVerified ? 'done' : 'action', - testId: 'dt_verification_phone_number_arrow_button', - text: isPhoneNumberVerified ? localize('Phone number verified') : localize('Your phone number'), - }, + ...(isPhoneNumberVerificationEnabled + ? [ + { + onClick: () => { + window.location.href = `${URLConstants.derivAppProduction}/account/personal-details`; + }, + phoneNumber: isPhoneNumberVerified ? phoneNumber : undefined, + status: isPhoneNumberVerified ? 'done' : 'action', + testId: 'dt_verification_phone_number_arrow_button', + text: isPhoneNumberVerified ? localize('Phone number verified') : localize('Your phone number'), + }, + ] + : []), { isDisabled: isPoiPending, onClick: () => { diff --git a/src/components/Verification/__tests__/Verification.spec.tsx b/src/components/Verification/__tests__/Verification.spec.tsx index c9fa07fc..2e4b79c0 100644 --- a/src/components/Verification/__tests__/Verification.spec.tsx +++ b/src/components/Verification/__tests__/Verification.spec.tsx @@ -16,6 +16,7 @@ let mockUsePoiPoaStatusData = { }; let mockUseGetPhoneNumberVerificationData = { + isPhoneNumberVerificationEnabled: false, isPhoneNumberVerified: false, phoneNumber: '1234567890', }; @@ -47,11 +48,20 @@ describe('', () => { expect(screen.getByTestId('dt_derivs-loader')).toBeInTheDocument(); }); - it('should ask user to upload their documents if isLoading is false and poi/poa status is none', () => { + it('should not show phone number verification if isPhoneNumberVerificationEnabled is false', () => { + render(); + expect(screen.queryByText('Your phone number')).not.toBeInTheDocument(); + }); + + it('should ask user to upload their documents and add their phone number if isLoading is false and poi/poa status is none and isPhoneNumberVerificationEnabled is true', () => { mockUsePoiPoaStatusData = { ...mockUsePoiPoaStatusData, isLoading: false, }; + mockUseGetPhoneNumberVerificationData = { + ...mockUseGetPhoneNumberVerificationData, + isPhoneNumberVerificationEnabled: true, + }; render(); diff --git a/src/hooks/api/settings/p2p-settings/useSettings.ts b/src/hooks/api/settings/p2p-settings/useSettings.ts index 84b51976..af9aacea 100644 --- a/src/hooks/api/settings/p2p-settings/useSettings.ts +++ b/src/hooks/api/settings/p2p-settings/useSettings.ts @@ -17,6 +17,8 @@ type TP2PSettings = isDisabled: boolean; isPaymentMethodsEnabled: boolean; localCurrency?: string; + pnv_required?: boolean; + poa_required?: boolean; rateType: 'fixed' | 'float'; reachedTargetDate: boolean; }) diff --git a/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts b/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts index 3bfd4bb6..ef93359d 100644 --- a/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts +++ b/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts @@ -8,22 +8,35 @@ const mockSettings = { }, }; +const mockP2PSettings = { + pnv_required: 0, +}; + jest.mock('@deriv-com/api-hooks', () => ({ useGetSettings: jest.fn(() => ({ data: mockSettings })), })); +jest.mock('../../api', () => ({ + settings: { + useSettings: jest.fn(() => ({ data: mockP2PSettings })), + }, +})); + describe('useGetPhoneNumberVerification', () => { - it('should return the phone number and false if the phone number is not verified', () => { + it('should return isPhoneNumberVerificationEnabled false, the phone number and false if the phone number is not verified', () => { const { result } = renderHook(() => useGetPhoneNumberVerification()); + expect(result.current.isPhoneNumberVerificationEnabled).toBe(false); expect(result.current.isPhoneNumberVerified).toBe(false); expect(result.current.phoneNumber).toBe('1234567890'); }); - it('should return the phone number and true if the phone number is verified', () => { + it('should return isPhoneNumberVerificationEnabled true, the phone number and true if the phone number is verified and pnv_required is true', () => { mockSettings.phone_number_verification.verified = 1; + mockP2PSettings.pnv_required = 1; const { result } = renderHook(() => useGetPhoneNumberVerification()); + expect(result.current.isPhoneNumberVerificationEnabled).toBe(true); expect(result.current.isPhoneNumberVerified).toBe(true); expect(result.current.phoneNumber).toBe('1234567890'); }); diff --git a/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts b/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts index b861a049..293daa41 100644 --- a/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts +++ b/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts @@ -1,12 +1,16 @@ import { useGetSettings } from '@deriv-com/api-hooks'; +import { api } from '..'; /** A custom hook that returns if the user's phone number is verified and the phone number */ const useGetPhoneNumberVerification = () => { const { data } = useGetSettings(); + const { data: p2pSettings } = api.settings.useSettings(); + + const isPhoneNumberVerificationEnabled = !!p2pSettings?.pnv_required; const isPhoneNumberVerified = !!data?.phone_number_verification?.verified; const phoneNumber = data?.phone; - return { isPhoneNumberVerified, phoneNumber }; + return { isPhoneNumberVerificationEnabled, isPhoneNumberVerified, phoneNumber }; }; export default useGetPhoneNumberVerification; From e91c7c42cb3b69dba17d6e8a27ffdc16dab05fdb Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Fri, 8 Nov 2024 13:07:43 +0800 Subject: [PATCH 04/13] chore: replaced p2p_poa_required with poa_required from p2p_settings --- src/hooks/custom-hooks/__tests__/usePoiPoaStatus.spec.tsx | 6 ++++++ src/hooks/custom-hooks/usePoiPoaStatus.ts | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/hooks/custom-hooks/__tests__/usePoiPoaStatus.spec.tsx b/src/hooks/custom-hooks/__tests__/usePoiPoaStatus.spec.tsx index 62e81025..2c7a1516 100644 --- a/src/hooks/custom-hooks/__tests__/usePoiPoaStatus.spec.tsx +++ b/src/hooks/custom-hooks/__tests__/usePoiPoaStatus.spec.tsx @@ -23,6 +23,12 @@ jest.mock('@deriv-com/api-hooks', () => ({ }), })); +jest.mock('../../api', () => ({ + settings: { + useSettings: jest.fn(() => ({ data: { poa_required: 1 } })), + }, +})); + const mockValues = { dataUpdatedAt: 0, error: null, diff --git a/src/hooks/custom-hooks/usePoiPoaStatus.ts b/src/hooks/custom-hooks/usePoiPoaStatus.ts index 65a98c5f..1d6cd051 100644 --- a/src/hooks/custom-hooks/usePoiPoaStatus.ts +++ b/src/hooks/custom-hooks/usePoiPoaStatus.ts @@ -1,9 +1,11 @@ import { useMemo } from 'react'; import { useGetAccountStatus } from '@deriv-com/api-hooks'; +import { api } from '..'; /** A custom hook that returns the POA, POI status and if POA is required for P2P */ const usePoiPoaStatus = () => { const { data, ...rest } = useGetAccountStatus(); + const { data: p2pSettings } = api.settings.useSettings(); // create new response for poi/poa statuses const modifiedAccountStatus = useMemo(() => { @@ -11,7 +13,7 @@ const usePoiPoaStatus = () => { const documentStatus = data?.authentication?.document?.status; const identityStatus = data?.authentication?.identity?.status; - const isP2PPoaRequired = data?.p2p_poa_required; + const isP2PPoaRequired = !!p2pSettings?.poa_required; const isPoaAuthenticatedWithIdv = data?.status.includes('poa_authenticated_with_idv') || data?.status.includes('poa_authenticated_with_idv_photo'); @@ -31,7 +33,7 @@ const usePoiPoaStatus = () => { poaStatus: documentStatus, poiStatus: identityStatus, }; - }, [data]); + }, [data, p2pSettings?.poa_required]); return { /** The POI & POA status. */ From ccd399f452ceeaa0eedc5845533ae101019c6b15 Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Fri, 8 Nov 2024 14:11:18 +0800 Subject: [PATCH 05/13] chore: handle showing Verification if pnv is enabled and updated test cases --- .../AdvertsTableRow/AdvertsTableRow.tsx | 19 +++++++++++++------ .../useGetPhoneNumberVerification.spec.ts | 11 ++++++++++- .../__tests__/usePoiPoaStatus.spec.tsx | 2 +- .../useGetPhoneNumberVerification.ts | 3 ++- .../__tests__/AdvertiserAdvertsTable.spec.tsx | 1 + .../__tests__/BuySellTable.spec.tsx | 1 + src/pages/my-ads/screens/MyAds/MyAds.tsx | 11 +++++++++-- .../screens/MyAds/__tests__/MyAds.spec.tsx | 16 ++++++++++++++-- .../screens/MyProfile/MyProfile.tsx | 4 +++- .../MyProfile/__tests__/MyProfile.spec.tsx | 19 ++++++++++++++++++- 10 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/components/AdvertsTableRow/AdvertsTableRow.tsx b/src/components/AdvertsTableRow/AdvertsTableRow.tsx index 5aa12806..7ef77606 100644 --- a/src/components/AdvertsTableRow/AdvertsTableRow.tsx +++ b/src/components/AdvertsTableRow/AdvertsTableRow.tsx @@ -4,10 +4,11 @@ import { useHistory, useLocation } from 'react-router-dom'; import { TAdvertsTableRowRenderer, TCurrency } from 'types'; import { Badge, BuySellForm, PaymentMethodLabel, StarRating, UserAvatar } from '@/components'; import { ErrorModal, NicknameModal } from '@/components/Modals'; -import { ADVERTISER_URL, BUY_SELL } from '@/constants'; +import { ADVERTISER_URL, BUY_SELL, BUY_SELL_URL } from '@/constants'; import { api } from '@/hooks'; import { useGetBusinessHours, + useGetPhoneNumberVerification, useIsAdvertiser, useIsAdvertiserBarred, useModalManager, @@ -29,6 +30,7 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => { const isBuySellPage = getCurrentRoute() === 'buy-sell'; const isAdvertiserBarred = useIsAdvertiserBarred(); const isAdvertiser = useIsAdvertiser(); + const { shouldShowVerification } = useGetPhoneNumberVerification(); const { data } = api.advertiser.useGetInfo() || {}; const { data: poiPoaData } = usePoiPoaStatus(); const { isPoiPoaVerified } = poiPoaData || {}; @@ -92,10 +94,15 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => { const redirectToVerification = () => { const searchParams = new URLSearchParams(location.search); searchParams.set('verified', 'false'); - history.replace({ - pathname: location.pathname, - search: searchParams.toString(), - }); + + if (!isBuySellPage) { + history.push(`${BUY_SELL_URL}?${searchParams.toString()}`); + } else { + history.replace({ + pathname: location.pathname, + search: searchParams.toString(), + }); + } }; const redirectToAdvertiser = () => { @@ -263,7 +270,7 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => { className='lg:min-w-[7.5rem]' disabled={isAdvertiserBarred || !isScheduleAvailable} onClick={() => { - if (!isAdvertiser && !isPoiPoaVerified) { + if (!isAdvertiser && (!isPoiPoaVerified || shouldShowVerification)) { redirectToVerification(); } else { setSelectedAdvertId(advertId); diff --git a/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts b/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts index ef93359d..36400898 100644 --- a/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts +++ b/src/hooks/custom-hooks/__tests__/useGetPhoneNumberVerification.spec.ts @@ -23,10 +23,11 @@ jest.mock('../../api', () => ({ })); describe('useGetPhoneNumberVerification', () => { - it('should return isPhoneNumberVerificationEnabled false, the phone number and false if the phone number is not verified', () => { + it('should return isPhoneNumberVerificationEnabled false, shouldShowVerification false, the phone number and false if the phone number is not verified', () => { const { result } = renderHook(() => useGetPhoneNumberVerification()); expect(result.current.isPhoneNumberVerificationEnabled).toBe(false); + expect(result.current.shouldShowVerification).toBe(false); expect(result.current.isPhoneNumberVerified).toBe(false); expect(result.current.phoneNumber).toBe('1234567890'); }); @@ -40,4 +41,12 @@ describe('useGetPhoneNumberVerification', () => { expect(result.current.isPhoneNumberVerified).toBe(true); expect(result.current.phoneNumber).toBe('1234567890'); }); + + it('should return shouldShowVerification true if the phone number is not verified and pnv_required is true', () => { + mockSettings.phone_number_verification.verified = 0; + mockP2PSettings.pnv_required = 1; + const { result } = renderHook(() => useGetPhoneNumberVerification()); + + expect(result.current.shouldShowVerification).toBe(true); + }); }); diff --git a/src/hooks/custom-hooks/__tests__/usePoiPoaStatus.spec.tsx b/src/hooks/custom-hooks/__tests__/usePoiPoaStatus.spec.tsx index 2c7a1516..10578796 100644 --- a/src/hooks/custom-hooks/__tests__/usePoiPoaStatus.spec.tsx +++ b/src/hooks/custom-hooks/__tests__/usePoiPoaStatus.spec.tsx @@ -107,7 +107,7 @@ describe('usePoiPoaStatus', () => { const { result } = renderHook(() => usePoiPoaStatus()); expect(result.current.data).toStrictEqual({ - isP2PPoaRequired: 0, + isP2PPoaRequired: true, isPoaAuthenticatedWithIdv: false, isPoaPending: false, isPoaVerified: true, diff --git a/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts b/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts index 293daa41..0a6f115f 100644 --- a/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts +++ b/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts @@ -8,9 +8,10 @@ const useGetPhoneNumberVerification = () => { const isPhoneNumberVerificationEnabled = !!p2pSettings?.pnv_required; const isPhoneNumberVerified = !!data?.phone_number_verification?.verified; + const shouldShowVerification = !isPhoneNumberVerified && isPhoneNumberVerificationEnabled; const phoneNumber = data?.phone; - return { isPhoneNumberVerificationEnabled, isPhoneNumberVerified, phoneNumber }; + return { isPhoneNumberVerificationEnabled, isPhoneNumberVerified, phoneNumber, shouldShowVerification }; }; export default useGetPhoneNumberVerification; diff --git a/src/pages/advertiser/screens/AdvertiserAdvertsTable/__tests__/AdvertiserAdvertsTable.spec.tsx b/src/pages/advertiser/screens/AdvertiserAdvertsTable/__tests__/AdvertiserAdvertsTable.spec.tsx index c0ab21bc..a5f0f654 100644 --- a/src/pages/advertiser/screens/AdvertiserAdvertsTable/__tests__/AdvertiserAdvertsTable.spec.tsx +++ b/src/pages/advertiser/screens/AdvertiserAdvertsTable/__tests__/AdvertiserAdvertsTable.spec.tsx @@ -98,6 +98,7 @@ const mockUseQueryString = { jest.mock('@/hooks/custom-hooks', () => ({ ...jest.requireActual('@/hooks/custom-hooks'), + useGetPhoneNumberVerification: jest.fn(() => ({ shouldShowVerification: false })), useIsAdvertiser: jest.fn(() => true), useIsAdvertiserBarred: jest.fn(() => false), useModalManager: jest.fn(() => mockUseModalManager), diff --git a/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx b/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx index f957c2e2..b8382b82 100644 --- a/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx +++ b/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx @@ -98,6 +98,7 @@ const mockUseQueryString = { jest.mock('@/hooks/custom-hooks', () => ({ ...jest.requireActual('@/hooks/custom-hooks'), + useGetPhoneNumberVerification: jest.fn(() => ({ shouldShowVerification: false })), useIsAdvertiser: jest.fn(() => mockUseIsAdvertiser), useIsAdvertiserBarred: jest.fn().mockReturnValue(false), useModalManager: jest.fn(() => mockUseModalManager), diff --git a/src/pages/my-ads/screens/MyAds/MyAds.tsx b/src/pages/my-ads/screens/MyAds/MyAds.tsx index c247a908..a45fb1d4 100644 --- a/src/pages/my-ads/screens/MyAds/MyAds.tsx +++ b/src/pages/my-ads/screens/MyAds/MyAds.tsx @@ -1,5 +1,11 @@ import { OutsideBusinessHoursHint, TemporarilyBarredHint, Verification } from '@/components'; -import { useGetBusinessHours, useIsAdvertiser, useIsAdvertiserBarred, usePoiPoaStatus } from '@/hooks/custom-hooks'; +import { + useGetBusinessHours, + useGetPhoneNumberVerification, + useIsAdvertiser, + useIsAdvertiserBarred, + usePoiPoaStatus, +} from '@/hooks/custom-hooks'; import { MyAdsTable } from './MyAdsTable'; const MyAds = () => { @@ -7,9 +13,10 @@ const MyAds = () => { const isAdvertiserBarred = useIsAdvertiserBarred(); const { isScheduleAvailable } = useGetBusinessHours(); const { data } = usePoiPoaStatus(); + const { shouldShowVerification } = useGetPhoneNumberVerification(); const { isPoiPoaVerified } = data || {}; - if (!isAdvertiser && !isPoiPoaVerified) + if (!isAdvertiser && (!isPoiPoaVerified || shouldShowVerification)) return (
; diff --git a/src/pages/my-ads/screens/MyAds/__tests__/MyAds.spec.tsx b/src/pages/my-ads/screens/MyAds/__tests__/MyAds.spec.tsx index 047904af..b0c0bcf8 100644 --- a/src/pages/my-ads/screens/MyAds/__tests__/MyAds.spec.tsx +++ b/src/pages/my-ads/screens/MyAds/__tests__/MyAds.spec.tsx @@ -1,4 +1,9 @@ -import { useGetBusinessHours, useIsAdvertiserBarred, usePoiPoaStatus } from '@/hooks/custom-hooks'; +import { + useGetBusinessHours, + useGetPhoneNumberVerification, + useIsAdvertiserBarred, + usePoiPoaStatus, +} from '@/hooks/custom-hooks'; import { render, screen } from '@testing-library/react'; import MyAds from '../MyAds'; @@ -13,6 +18,9 @@ jest.mock('@/hooks/custom-hooks', () => ({ useGetBusinessHours: jest.fn().mockReturnValue({ isScheduleAvailable: true, }), + useGetPhoneNumberVerification: jest.fn().mockReturnValue({ + shouldShowVerification: false, + }), useIsAdvertiser: jest.fn(() => false), useIsAdvertiserBarred: jest.fn().mockReturnValue(false), usePoiPoaStatus: jest.fn().mockReturnValue({ @@ -36,6 +44,7 @@ jest.mock('../MyAdsTable', () => ({ })); const mockUseGetBusinessHours = useGetBusinessHours as jest.Mock; +const mockUseGetPhoneNumberVerification = useGetPhoneNumberVerification as jest.Mock; const mockUseIsAdvertiserBarred = useIsAdvertiserBarred as jest.MockedFunction; const mockUsePoiPoaStatus = usePoiPoaStatus as jest.MockedFunction; @@ -64,12 +73,15 @@ describe('MyAds', () => { expect(screen.queryByText('TemporarilyBarredHint')).not.toBeInTheDocument(); }); - it('should render the Verification component if POA/POI is not verified is false', () => { + it('should render the Verification component if POA/POI is not verified and shouldShowVerification is true', () => { (mockUsePoiPoaStatus as jest.Mock).mockReturnValue({ data: { isPoiPoaVerified: false, }, }); + mockUseGetPhoneNumberVerification.mockReturnValue({ + shouldShowVerification: true, + }); render(); expect(screen.getByText('Verification')).toBeInTheDocument(); }); diff --git a/src/pages/my-profile/screens/MyProfile/MyProfile.tsx b/src/pages/my-profile/screens/MyProfile/MyProfile.tsx index 712e5cf7..e73c618e 100644 --- a/src/pages/my-profile/screens/MyProfile/MyProfile.tsx +++ b/src/pages/my-profile/screens/MyProfile/MyProfile.tsx @@ -3,6 +3,7 @@ import { ProfileContent, Verification } from '@/components'; import { NicknameModal } from '@/components/Modals'; import { useAdvertiserStats, + useGetPhoneNumberVerification, useIsAdvertiser, useModalManager, usePoiPoaStatus, @@ -27,6 +28,7 @@ const MyProfile = () => { const { data } = usePoiPoaStatus(); const { data: advertiserStats, isLoading } = useAdvertiserStats(); const { isPoiPoaVerified } = data || {}; + const { shouldShowVerification } = useGetPhoneNumberVerification(); const isAdvertiser = useIsAdvertiser(); const { hideModal, isModalOpenFor, showModal } = useModalManager({ shouldReinitializeModals: false }); @@ -48,7 +50,7 @@ const MyProfile = () => { return ; } - if (!isAdvertiser && !isPoiPoaVerified) { + if (!isAdvertiser && (!isPoiPoaVerified || shouldShowVerification)) { return (
diff --git a/src/pages/my-profile/screens/MyProfile/__tests__/MyProfile.spec.tsx b/src/pages/my-profile/screens/MyProfile/__tests__/MyProfile.spec.tsx index dd90719b..958f2e55 100644 --- a/src/pages/my-profile/screens/MyProfile/__tests__/MyProfile.spec.tsx +++ b/src/pages/my-profile/screens/MyProfile/__tests__/MyProfile.spec.tsx @@ -1,4 +1,9 @@ -import { useAdvertiserStats, useIsAdvertiser, usePoiPoaStatus } from '@/hooks/custom-hooks'; +import { + useAdvertiserStats, + useGetPhoneNumberVerification, + useIsAdvertiser, + usePoiPoaStatus, +} from '@/hooks/custom-hooks'; import { useDevice } from '@deriv-com/ui'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -45,6 +50,7 @@ jest.mock('../MyProfileMobile', () => ({ })); const mockUseDevice = useDevice as jest.MockedFunction; +const mockUseGetPhoneNumberVerification = useGetPhoneNumberVerification as jest.Mock; const mockUsePoiPoaStatus = usePoiPoaStatus as jest.MockedFunction; const mockUseAdvertiserStats = useAdvertiserStats as jest.MockedFunction; const mockUseIsAdvertiser = useIsAdvertiser as jest.MockedFunction; @@ -62,6 +68,9 @@ jest.mock('@/hooks/custom-hooks', () => ({ error: undefined, isLoading: false, }), + useGetPhoneNumberVerification: jest.fn().mockReturnValue({ + shouldShowVerification: false, + }), useIsAdvertiser: jest.fn().mockReturnValue(true), useModalManager: jest.fn(() => mockModalManager), usePoiPoaStatus: jest.fn().mockReturnValue({ @@ -115,6 +124,14 @@ describe('MyProfile', () => { render(); expect(screen.getByText('Verification')).toBeInTheDocument(); }); + it('should not render the verification component if the user has completed POI and POA and shouldShowVerification is false', () => { + (mockUseGetPhoneNumberVerification as jest.Mock).mockReturnValueOnce({ + shouldShowVerification: false, + }); + + render(); + expect(screen.queryByText('Verification')).not.toBeInTheDocument(); + }); it('should show the nickname modal if user has completed POI or POA for the first time', () => { (mockUsePoiPoaStatus as jest.Mock).mockReturnValueOnce({ data: { isPoiPoaVerified: true }, From e35734655680e8b030f8e3bb6f054283a1fdb908 Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Fri, 8 Nov 2024 15:59:52 +0800 Subject: [PATCH 06/13] chore: added edge case when trying to block/unblock user before user is verified --- .../Modals/BlockUnblockUserModal/BlockUnblockUserModal.tsx | 5 ++++- src/constants/api-error-codes.ts | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/Modals/BlockUnblockUserModal/BlockUnblockUserModal.tsx b/src/components/Modals/BlockUnblockUserModal/BlockUnblockUserModal.tsx index ab3d5d8c..bab8fbd0 100644 --- a/src/components/Modals/BlockUnblockUserModal/BlockUnblockUserModal.tsx +++ b/src/components/Modals/BlockUnblockUserModal/BlockUnblockUserModal.tsx @@ -84,7 +84,10 @@ const BlockUnblockUserModal = ({ }; const blockUnblockError = errorMessages.find( - error => error.code === ERROR_CODES.PERMISSION_DENIED || error.code === ERROR_CODES.INVALID_ADVERTISER_ID + error => + error.code === ERROR_CODES.PERMISSION_DENIED || + error.code === ERROR_CODES.INVALID_ADVERTISER_ID || + error.code === ERROR_CODES.ADVERTISER_NOT_REGISTERED ); if (blockUnblockError && isModalOpenFor('ErrorModal')) { diff --git a/src/constants/api-error-codes.ts b/src/constants/api-error-codes.ts index 5a30fa9c..7afcc6fe 100644 --- a/src/constants/api-error-codes.ts +++ b/src/constants/api-error-codes.ts @@ -9,6 +9,7 @@ export const ERROR_CODES = { ADVERT_SAME_LIMITS: 'AdvertSameLimits', ADVERTISER_ADS_PAUSED: 'advertiser_ads_paused', ADVERTISER_NOT_FOUND: 'AdvertiserNotFound', + ADVERTISER_NOT_REGISTERED: 'AdvertiserNotRegistered', ADVERTISER_SCHEDULE: 'advertiser_schedule', ADVERTISER_SCHEDULE_AVAILABILITY: 'AdvertiserScheduleAvailability', ADVERTISER_TEMP_BAN: 'advertiser_temp_ban', From 79c5675eae515b48b5cb4b30f911a72b2e43e2fc Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Fri, 8 Nov 2024 16:02:57 +0800 Subject: [PATCH 07/13] chore: updated documentation for useGetPhoneNumberVerification hook --- src/hooks/custom-hooks/useGetPhoneNumberVerification.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts b/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts index 0a6f115f..ed5d1423 100644 --- a/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts +++ b/src/hooks/custom-hooks/useGetPhoneNumberVerification.ts @@ -1,7 +1,11 @@ import { useGetSettings } from '@deriv-com/api-hooks'; import { api } from '..'; -/** A custom hook that returns if the user's phone number is verified and the phone number */ +/** A custom hook that returns if phone number verification is enabled, + * if the user's phone number is verified, should show verification component, + * and the phone number + * + * */ const useGetPhoneNumberVerification = () => { const { data } = useGetSettings(); const { data: p2pSettings } = api.settings.useSettings(); From 85edc27e8eddf6a40aa00ef0d00ebbcd46bb2157 Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Mon, 11 Nov 2024 14:23:33 +0800 Subject: [PATCH 08/13] chore: added new hook useIsAdvertiserNotVerified --- .../AdvertsTableRow/AdvertsTableRow.tsx | 6 ++-- src/hooks/custom-hooks/index.ts | 1 + .../useIsAdvertiserNotVerified.ts | 15 +++++++++ .../__tests__/BuySellTable.spec.tsx | 2 +- src/pages/my-ads/screens/MyAds/MyAds.tsx | 15 ++------- .../screens/MyAds/__tests__/MyAds.spec.tsx | 33 +++---------------- .../screens/MyProfile/MyProfile.tsx | 6 ++-- .../MyProfile/__tests__/MyProfile.spec.tsx | 22 ++++--------- 8 files changed, 37 insertions(+), 63 deletions(-) create mode 100644 src/hooks/custom-hooks/useIsAdvertiserNotVerified.ts diff --git a/src/components/AdvertsTableRow/AdvertsTableRow.tsx b/src/components/AdvertsTableRow/AdvertsTableRow.tsx index 7ef77606..f45e0713 100644 --- a/src/components/AdvertsTableRow/AdvertsTableRow.tsx +++ b/src/components/AdvertsTableRow/AdvertsTableRow.tsx @@ -8,9 +8,9 @@ import { ADVERTISER_URL, BUY_SELL, BUY_SELL_URL } from '@/constants'; import { api } from '@/hooks'; import { useGetBusinessHours, - useGetPhoneNumberVerification, useIsAdvertiser, useIsAdvertiserBarred, + useIsAdvertiserNotVerified, useModalManager, usePoiPoaStatus, } from '@/hooks/custom-hooks'; @@ -30,13 +30,13 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => { const isBuySellPage = getCurrentRoute() === 'buy-sell'; const isAdvertiserBarred = useIsAdvertiserBarred(); const isAdvertiser = useIsAdvertiser(); - const { shouldShowVerification } = useGetPhoneNumberVerification(); const { data } = api.advertiser.useGetInfo() || {}; const { data: poiPoaData } = usePoiPoaStatus(); const { isPoiPoaVerified } = poiPoaData || {}; const { localize } = useTranslations(); const { hasCreatedAdvertiser } = useAdvertiserInfoState(); const { isScheduleAvailable } = useGetBusinessHours(); + const isAdvertiserNotVerified = useIsAdvertiserNotVerified(); const { account_currency: accountCurrency, @@ -270,7 +270,7 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => { className='lg:min-w-[7.5rem]' disabled={isAdvertiserBarred || !isScheduleAvailable} onClick={() => { - if (!isAdvertiser && (!isPoiPoaVerified || shouldShowVerification)) { + if (isAdvertiserNotVerified) { redirectToVerification(); } else { setSelectedAdvertId(advertId); diff --git a/src/hooks/custom-hooks/index.ts b/src/hooks/custom-hooks/index.ts index 562636ff..a2c41ebe 100644 --- a/src/hooks/custom-hooks/index.ts +++ b/src/hooks/custom-hooks/index.ts @@ -13,6 +13,7 @@ export { default as useGrowthbookGetFeatureValue } from './useGrowthbookGetFeatu export { default as useHandleRouteChange } from './useHandleRouteChange'; export { default as useIsAdvertiser } from './useIsAdvertiser'; export { default as useIsAdvertiserBarred } from './useIsAdvertiserBarred'; +export { default as useIsAdvertiserNotVerified } from './useIsAdvertiserNotVerified.ts'; export { default as useIsP2PBlocked } from './useIsP2PBlocked'; export { default as useIsRtl } from './useIsRtl'; export { default as useLiveChat } from './useLiveChat'; diff --git a/src/hooks/custom-hooks/useIsAdvertiserNotVerified.ts b/src/hooks/custom-hooks/useIsAdvertiserNotVerified.ts new file mode 100644 index 00000000..77709700 --- /dev/null +++ b/src/hooks/custom-hooks/useIsAdvertiserNotVerified.ts @@ -0,0 +1,15 @@ +import useGetPhoneNumberVerification from './useGetPhoneNumberVerification'; +import useIsAdvertiser from './useIsAdvertiser'; +import usePoiPoaStatus from './usePoiPoaStatus'; + +const useIsAdvertiserNotVerified = () => { + const { shouldShowVerification } = useGetPhoneNumberVerification(); + const { data } = usePoiPoaStatus(); + const isPoiPoaVerified = data?.isPoiPoaVerified; + const isAdvertiser = useIsAdvertiser(); + const isAdvertiserNotVerified = !isAdvertiser && (!isPoiPoaVerified || shouldShowVerification); + + return isAdvertiserNotVerified; +}; + +export default useIsAdvertiserNotVerified; diff --git a/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx b/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx index b8382b82..8d9070f8 100644 --- a/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx +++ b/src/pages/buy-sell/screens/BuySellTable/__tests__/BuySellTable.spec.tsx @@ -98,9 +98,9 @@ const mockUseQueryString = { jest.mock('@/hooks/custom-hooks', () => ({ ...jest.requireActual('@/hooks/custom-hooks'), - useGetPhoneNumberVerification: jest.fn(() => ({ shouldShowVerification: false })), useIsAdvertiser: jest.fn(() => mockUseIsAdvertiser), useIsAdvertiserBarred: jest.fn().mockReturnValue(false), + useIsAdvertiserNotVerified: jest.fn(() => true), useModalManager: jest.fn(() => mockUseModalManager), usePoiPoaStatus: jest.fn(() => ({ data: { isPoaVerified: true, isPoiVerified: true } })), useQueryString: jest.fn(() => mockUseQueryString), diff --git a/src/pages/my-ads/screens/MyAds/MyAds.tsx b/src/pages/my-ads/screens/MyAds/MyAds.tsx index a45fb1d4..bdaa3a6f 100644 --- a/src/pages/my-ads/screens/MyAds/MyAds.tsx +++ b/src/pages/my-ads/screens/MyAds/MyAds.tsx @@ -1,22 +1,13 @@ import { OutsideBusinessHoursHint, TemporarilyBarredHint, Verification } from '@/components'; -import { - useGetBusinessHours, - useGetPhoneNumberVerification, - useIsAdvertiser, - useIsAdvertiserBarred, - usePoiPoaStatus, -} from '@/hooks/custom-hooks'; +import { useGetBusinessHours, useIsAdvertiserBarred, useIsAdvertiserNotVerified } from '@/hooks/custom-hooks'; import { MyAdsTable } from './MyAdsTable'; const MyAds = () => { - const isAdvertiser = useIsAdvertiser(); const isAdvertiserBarred = useIsAdvertiserBarred(); const { isScheduleAvailable } = useGetBusinessHours(); - const { data } = usePoiPoaStatus(); - const { shouldShowVerification } = useGetPhoneNumberVerification(); - const { isPoiPoaVerified } = data || {}; + const isAdvertiserNotVerified = useIsAdvertiserNotVerified(); - if (!isAdvertiser && (!isPoiPoaVerified || shouldShowVerification)) + if (isAdvertiserNotVerified) return (
; diff --git a/src/pages/my-ads/screens/MyAds/__tests__/MyAds.spec.tsx b/src/pages/my-ads/screens/MyAds/__tests__/MyAds.spec.tsx index b0c0bcf8..4f18c046 100644 --- a/src/pages/my-ads/screens/MyAds/__tests__/MyAds.spec.tsx +++ b/src/pages/my-ads/screens/MyAds/__tests__/MyAds.spec.tsx @@ -1,9 +1,4 @@ -import { - useGetBusinessHours, - useGetPhoneNumberVerification, - useIsAdvertiserBarred, - usePoiPoaStatus, -} from '@/hooks/custom-hooks'; +import { useGetBusinessHours, useIsAdvertiserBarred, useIsAdvertiserNotVerified } from '@/hooks/custom-hooks'; import { render, screen } from '@testing-library/react'; import MyAds from '../MyAds'; @@ -18,18 +13,8 @@ jest.mock('@/hooks/custom-hooks', () => ({ useGetBusinessHours: jest.fn().mockReturnValue({ isScheduleAvailable: true, }), - useGetPhoneNumberVerification: jest.fn().mockReturnValue({ - shouldShowVerification: false, - }), - useIsAdvertiser: jest.fn(() => false), useIsAdvertiserBarred: jest.fn().mockReturnValue(false), - usePoiPoaStatus: jest.fn().mockReturnValue({ - data: { - isPoaVerified: true, - isPoiPoaVerified: true, - isPoiVerified: true, - }, - }), + useIsAdvertiserNotVerified: jest.fn(() => false), })); jest.mock('@deriv-com/ui', () => ({ @@ -44,9 +29,8 @@ jest.mock('../MyAdsTable', () => ({ })); const mockUseGetBusinessHours = useGetBusinessHours as jest.Mock; -const mockUseGetPhoneNumberVerification = useGetPhoneNumberVerification as jest.Mock; +const mockUseIsAdvertiserNotVerified = useIsAdvertiserNotVerified as jest.Mock; const mockUseIsAdvertiserBarred = useIsAdvertiserBarred as jest.MockedFunction; -const mockUsePoiPoaStatus = usePoiPoaStatus as jest.MockedFunction; describe('MyAds', () => { it('should render the MyAdsTable component', () => { @@ -73,15 +57,8 @@ describe('MyAds', () => { expect(screen.queryByText('TemporarilyBarredHint')).not.toBeInTheDocument(); }); - it('should render the Verification component if POA/POI is not verified and shouldShowVerification is true', () => { - (mockUsePoiPoaStatus as jest.Mock).mockReturnValue({ - data: { - isPoiPoaVerified: false, - }, - }); - mockUseGetPhoneNumberVerification.mockReturnValue({ - shouldShowVerification: true, - }); + it('should render the Verification component if advertiser is not verified', () => { + mockUseIsAdvertiserNotVerified.mockReturnValue(true); render(); expect(screen.getByText('Verification')).toBeInTheDocument(); }); diff --git a/src/pages/my-profile/screens/MyProfile/MyProfile.tsx b/src/pages/my-profile/screens/MyProfile/MyProfile.tsx index e73c618e..81415f1d 100644 --- a/src/pages/my-profile/screens/MyProfile/MyProfile.tsx +++ b/src/pages/my-profile/screens/MyProfile/MyProfile.tsx @@ -3,8 +3,8 @@ import { ProfileContent, Verification } from '@/components'; import { NicknameModal } from '@/components/Modals'; import { useAdvertiserStats, - useGetPhoneNumberVerification, useIsAdvertiser, + useIsAdvertiserNotVerified, useModalManager, usePoiPoaStatus, useQueryString, @@ -28,8 +28,8 @@ const MyProfile = () => { const { data } = usePoiPoaStatus(); const { data: advertiserStats, isLoading } = useAdvertiserStats(); const { isPoiPoaVerified } = data || {}; - const { shouldShowVerification } = useGetPhoneNumberVerification(); const isAdvertiser = useIsAdvertiser(); + const isAdvertiserNotVerified = useIsAdvertiserNotVerified(); const { hideModal, isModalOpenFor, showModal } = useModalManager({ shouldReinitializeModals: false }); const currentTab = queryString.tab; @@ -50,7 +50,7 @@ const MyProfile = () => { return ; } - if (!isAdvertiser && (!isPoiPoaVerified || shouldShowVerification)) { + if (isAdvertiserNotVerified) { return (
diff --git a/src/pages/my-profile/screens/MyProfile/__tests__/MyProfile.spec.tsx b/src/pages/my-profile/screens/MyProfile/__tests__/MyProfile.spec.tsx index 958f2e55..26cbfd27 100644 --- a/src/pages/my-profile/screens/MyProfile/__tests__/MyProfile.spec.tsx +++ b/src/pages/my-profile/screens/MyProfile/__tests__/MyProfile.spec.tsx @@ -1,9 +1,4 @@ -import { - useAdvertiserStats, - useGetPhoneNumberVerification, - useIsAdvertiser, - usePoiPoaStatus, -} from '@/hooks/custom-hooks'; +import { useAdvertiserStats, useIsAdvertiser, useIsAdvertiserNotVerified, usePoiPoaStatus } from '@/hooks/custom-hooks'; import { useDevice } from '@deriv-com/ui'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -50,10 +45,10 @@ jest.mock('../MyProfileMobile', () => ({ })); const mockUseDevice = useDevice as jest.MockedFunction; -const mockUseGetPhoneNumberVerification = useGetPhoneNumberVerification as jest.Mock; const mockUsePoiPoaStatus = usePoiPoaStatus as jest.MockedFunction; const mockUseAdvertiserStats = useAdvertiserStats as jest.MockedFunction; const mockUseIsAdvertiser = useIsAdvertiser as jest.MockedFunction; +const mockUseIsAdvertiserNotVerified = useIsAdvertiserNotVerified as jest.Mock; const mockModalManager = { hideModal: jest.fn(), isModalOpenFor: jest.fn().mockReturnValue(false), @@ -68,10 +63,8 @@ jest.mock('@/hooks/custom-hooks', () => ({ error: undefined, isLoading: false, }), - useGetPhoneNumberVerification: jest.fn().mockReturnValue({ - shouldShowVerification: false, - }), useIsAdvertiser: jest.fn().mockReturnValue(true), + useIsAdvertiserNotVerified: jest.fn().mockReturnValue(false), useModalManager: jest.fn(() => mockModalManager), usePoiPoaStatus: jest.fn().mockReturnValue({ data: { @@ -105,7 +98,7 @@ describe('MyProfile', () => { expect(screen.getByTestId('dt_derivs-loader')).toBeInTheDocument(); }); it('should render the verification component if a new user has not completed POI ', () => { - (mockUseIsAdvertiser as jest.Mock).mockReturnValueOnce(false); + (mockUseIsAdvertiserNotVerified as jest.Mock).mockReturnValueOnce(true); (mockUsePoiPoaStatus as jest.Mock).mockReturnValueOnce({ data: { isPoaVerified: true, isPoiVerified: false }, isLoading: false, @@ -115,7 +108,7 @@ describe('MyProfile', () => { expect(screen.getByText('Verification')).toBeInTheDocument(); }); it('should render the verification component if a new user has not completed POA', () => { - (mockUseIsAdvertiser as jest.Mock).mockReturnValueOnce(false); + (mockUseIsAdvertiserNotVerified as jest.Mock).mockReturnValueOnce(true); (mockUsePoiPoaStatus as jest.Mock).mockReturnValueOnce({ data: { isPoaVerified: false, isPoiVerified: true }, isLoading: false, @@ -125,10 +118,7 @@ describe('MyProfile', () => { expect(screen.getByText('Verification')).toBeInTheDocument(); }); it('should not render the verification component if the user has completed POI and POA and shouldShowVerification is false', () => { - (mockUseGetPhoneNumberVerification as jest.Mock).mockReturnValueOnce({ - shouldShowVerification: false, - }); - + (mockUseIsAdvertiserNotVerified as jest.Mock).mockReturnValueOnce(false); render(); expect(screen.queryByText('Verification')).not.toBeInTheDocument(); }); From f61bd9e20759cae2110fe46c0720e6e9ea875bbc Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Mon, 11 Nov 2024 14:38:58 +0800 Subject: [PATCH 09/13] chore: added test cases for useIsAdvertiserNotVerified --- .../useIsAdvertiserNotVerified.spec.ts | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/hooks/custom-hooks/__tests__/useIsAdvertiserNotVerified.spec.ts diff --git a/src/hooks/custom-hooks/__tests__/useIsAdvertiserNotVerified.spec.ts b/src/hooks/custom-hooks/__tests__/useIsAdvertiserNotVerified.spec.ts new file mode 100644 index 00000000..859afd3b --- /dev/null +++ b/src/hooks/custom-hooks/__tests__/useIsAdvertiserNotVerified.spec.ts @@ -0,0 +1,55 @@ +import { renderHook } from '@testing-library/react'; +import useGetPhoneNumberVerification from '../useGetPhoneNumberVerification'; +import useIsAdvertiser from '../useIsAdvertiser'; +import useIsAdvertiserNotVerified from '../useIsAdvertiserNotVerified'; +import usePoiPoaStatus from '../usePoiPoaStatus'; + +jest.mock('../useGetPhoneNumberVerification'); +jest.mock('../useIsAdvertiser'); +jest.mock('../usePoiPoaStatus'); + +const mockUseGetPhoneNumberVerification = useGetPhoneNumberVerification as jest.Mock; +const mockUseIsAdvertiser = useIsAdvertiser as jest.Mock; +const mockUsePoiPoaStatus = usePoiPoaStatus as jest.Mock; + +describe('useIsAdvertiserNotVerified', () => { + it('should return true if user is not an advertiser and POI/POA is not verified', () => { + mockUseGetPhoneNumberVerification.mockReturnValue({ shouldShowVerification: false }); + mockUseIsAdvertiser.mockReturnValue(false); + mockUsePoiPoaStatus.mockReturnValue({ data: { isPoiPoaVerified: false } }); + + const { result } = renderHook(() => useIsAdvertiserNotVerified()); + + expect(result.current).toBe(true); + }); + + it('should return true if user is not an advertiser and should show verification', () => { + mockUseGetPhoneNumberVerification.mockReturnValue({ shouldShowVerification: true }); + mockUseIsAdvertiser.mockReturnValue(false); + mockUsePoiPoaStatus.mockReturnValue({ data: { isPoiPoaVerified: true } }); + + const { result } = renderHook(() => useIsAdvertiserNotVerified()); + + expect(result.current).toBe(true); + }); + + it('should return false if user is an advertiser', () => { + mockUseGetPhoneNumberVerification.mockReturnValue({ shouldShowVerification: true }); + mockUseIsAdvertiser.mockReturnValue(true); + mockUsePoiPoaStatus.mockReturnValue({ data: { isPoiPoaVerified: false } }); + + const { result } = renderHook(() => useIsAdvertiserNotVerified()); + + expect(result.current).toBe(false); + }); + + it('should return false if user is not an advertiser but POI/POA is verified and should not show verification', () => { + mockUseGetPhoneNumberVerification.mockReturnValue({ shouldShowVerification: false }); + mockUseIsAdvertiser.mockReturnValue(false); + mockUsePoiPoaStatus.mockReturnValue({ data: { isPoiPoaVerified: true } }); + + const { result } = renderHook(() => useIsAdvertiserNotVerified()); + + expect(result.current).toBe(false); + }); +}); From 9433785f6f643c3fb6a9d488a7233b5fff4e1d79 Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Mon, 11 Nov 2024 15:30:47 +0800 Subject: [PATCH 10/13] fix: failing test cases for AdvertiserAdvertsTable --- .../__tests__/AdvertiserAdvertsTable.spec.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/advertiser/screens/AdvertiserAdvertsTable/__tests__/AdvertiserAdvertsTable.spec.tsx b/src/pages/advertiser/screens/AdvertiserAdvertsTable/__tests__/AdvertiserAdvertsTable.spec.tsx index a5f0f654..6a7e7467 100644 --- a/src/pages/advertiser/screens/AdvertiserAdvertsTable/__tests__/AdvertiserAdvertsTable.spec.tsx +++ b/src/pages/advertiser/screens/AdvertiserAdvertsTable/__tests__/AdvertiserAdvertsTable.spec.tsx @@ -98,9 +98,9 @@ const mockUseQueryString = { jest.mock('@/hooks/custom-hooks', () => ({ ...jest.requireActual('@/hooks/custom-hooks'), - useGetPhoneNumberVerification: jest.fn(() => ({ shouldShowVerification: false })), useIsAdvertiser: jest.fn(() => true), useIsAdvertiserBarred: jest.fn(() => false), + useIsAdvertiserNotVerified: jest.fn(() => false), useModalManager: jest.fn(() => mockUseModalManager), usePoiPoaStatus: jest.fn(() => ({ data: { isPoaVerified: true, isPoiVerified: true } })), useQueryString: jest.fn(() => mockUseQueryString), From f74cb9cecefe791d423f2dfde746dcac5a043a20 Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Tue, 10 Dec 2024 14:23:53 +0800 Subject: [PATCH 11/13] chore: added Mobile verified badge --- .../AdvertiserName/AdvertiserNameBadges.tsx | 9 +++++++++ .../__tests__/AdvertiserNameBadges.spec.tsx | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/components/AdvertiserName/AdvertiserNameBadges.tsx b/src/components/AdvertiserName/AdvertiserNameBadges.tsx index 4fe43feb..0aff6b06 100644 --- a/src/components/AdvertiserName/AdvertiserNameBadges.tsx +++ b/src/components/AdvertiserName/AdvertiserNameBadges.tsx @@ -1,5 +1,6 @@ import { DeepPartial, TAdvertiserStats } from 'types'; import { Badge } from '@/components'; +import { useGetPhoneNumberVerification } from '@/hooks'; import { useTranslations } from '@deriv-com/translations'; import './AdvertiserNameBadges.scss'; @@ -11,6 +12,7 @@ import './AdvertiserNameBadges.scss'; */ const AdvertiserNameBadges = ({ advertiserStats }: { advertiserStats: DeepPartial }) => { const { isAddressVerified, isIdentityVerified, totalOrders } = advertiserStats || {}; + const { isPhoneNumberVerificationEnabled, isPhoneNumberVerified } = useGetPhoneNumberVerification(); const { localize } = useTranslations(); const getStatus = (isVerified?: boolean) => (isVerified ? localize('verified') : localize('not verified')); const getVariant = (isVerified?: boolean) => (isVerified ? 'success' : 'general'); @@ -28,6 +30,13 @@ const AdvertiserNameBadges = ({ advertiserStats }: { advertiserStats: DeepPartia status={getStatus(isAddressVerified)} variant={getVariant(isAddressVerified)} /> + {isPhoneNumberVerificationEnabled && ( + + )}
); }; diff --git a/src/components/AdvertiserName/__tests__/AdvertiserNameBadges.spec.tsx b/src/components/AdvertiserName/__tests__/AdvertiserNameBadges.spec.tsx index 941131b9..a25316a2 100644 --- a/src/components/AdvertiserName/__tests__/AdvertiserNameBadges.spec.tsx +++ b/src/components/AdvertiserName/__tests__/AdvertiserNameBadges.spec.tsx @@ -10,9 +10,15 @@ const mockUseAdvertiserStats = { isLoading: false, }; +const mockUseGetPhoneNumberVerification = { + isPhoneNumberVerificationEnabled: false, + isPhoneNumberVerified: false, +}; + jest.mock('@/hooks/custom-hooks', () => ({ ...jest.requireActual('@/hooks/custom-hooks'), useAdvertiserStats: jest.fn(() => mockUseAdvertiserStats), + useGetPhoneNumberVerification: jest.fn(() => mockUseGetPhoneNumberVerification), })); const mockProps = { @@ -56,4 +62,16 @@ describe('AdvertiserNameBadges', () => { render(); expect(screen.getByText('100+')).toBeInTheDocument(); }); + it('should render mobile badge when phone number verification is enabled and not verified', () => { + mockUseGetPhoneNumberVerification.isPhoneNumberVerificationEnabled = true; + render(); + expect(screen.getByText('Mobile')).toBeInTheDocument(); + expect(screen.getByText('not verified')).toBeInTheDocument(); + }); + it('should render mobile badge with verified status when phone number verification is enabled and verified', () => { + mockUseGetPhoneNumberVerification.isPhoneNumberVerified = true; + render(); + expect(screen.getByText('Mobile')).toBeInTheDocument(); + expect(screen.getAllByText('verified')).toHaveLength(3); + }); }); From 02956c0fbeb400f45eb610f94aaf6ecd17ecb0fa Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Tue, 10 Dec 2024 14:42:09 +0800 Subject: [PATCH 12/13] fix: failing AdvertiserName.spec.tsx test cases --- src/components/AdvertiserName/AdvertiserNameBadges.tsx | 2 +- .../AdvertiserName/__tests__/AdvertiserName.spec.tsx | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/AdvertiserName/AdvertiserNameBadges.tsx b/src/components/AdvertiserName/AdvertiserNameBadges.tsx index 0aff6b06..0e9870a1 100644 --- a/src/components/AdvertiserName/AdvertiserNameBadges.tsx +++ b/src/components/AdvertiserName/AdvertiserNameBadges.tsx @@ -1,6 +1,6 @@ import { DeepPartial, TAdvertiserStats } from 'types'; import { Badge } from '@/components'; -import { useGetPhoneNumberVerification } from '@/hooks'; +import { useGetPhoneNumberVerification } from '@/hooks/custom-hooks'; import { useTranslations } from '@deriv-com/translations'; import './AdvertiserNameBadges.scss'; diff --git a/src/components/AdvertiserName/__tests__/AdvertiserName.spec.tsx b/src/components/AdvertiserName/__tests__/AdvertiserName.spec.tsx index 9188a361..19de24d0 100644 --- a/src/components/AdvertiserName/__tests__/AdvertiserName.spec.tsx +++ b/src/components/AdvertiserName/__tests__/AdvertiserName.spec.tsx @@ -16,6 +16,16 @@ const mockModalManager = { showModal: jest.fn(), }; jest.mock('@/hooks', () => ({ + ...jest.requireActual('@/hooks'), + api: { + settings: { + useSettings: jest.fn(() => ({ pnv_required: false })), + }, + }, + useGetPhoneNumberVerification: jest.fn(() => ({ + isPhoneNumberVerificationEnabled: false, + isPhoneNumberVerified: false, + })), useIsRtl: jest.fn(() => false), useModalManager: jest.fn(() => mockModalManager), })); From 447bbf438ad07b95d6034b417481619ba6dcebb9 Mon Sep 17 00:00:00 2001 From: ameerul-deriv Date: Wed, 11 Dec 2024 15:05:30 +0800 Subject: [PATCH 13/13] chore: show only mobile verification badge in my profile --- src/components/AdvertiserName/AdvertiserNameBadges.tsx | 4 +++- .../AdvertiserName/__tests__/AdvertiserNameBadges.spec.tsx | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/AdvertiserName/AdvertiserNameBadges.tsx b/src/components/AdvertiserName/AdvertiserNameBadges.tsx index 0e9870a1..b380b9cf 100644 --- a/src/components/AdvertiserName/AdvertiserNameBadges.tsx +++ b/src/components/AdvertiserName/AdvertiserNameBadges.tsx @@ -1,6 +1,7 @@ import { DeepPartial, TAdvertiserStats } from 'types'; import { Badge } from '@/components'; import { useGetPhoneNumberVerification } from '@/hooks/custom-hooks'; +import { getCurrentRoute } from '@/utils'; import { useTranslations } from '@deriv-com/translations'; import './AdvertiserNameBadges.scss'; @@ -16,6 +17,7 @@ const AdvertiserNameBadges = ({ advertiserStats }: { advertiserStats: DeepPartia const { localize } = useTranslations(); const getStatus = (isVerified?: boolean) => (isVerified ? localize('verified') : localize('not verified')); const getVariant = (isVerified?: boolean) => (isVerified ? 'success' : 'general'); + const isMyProfile = getCurrentRoute() === 'my-profile'; return (
@@ -30,7 +32,7 @@ const AdvertiserNameBadges = ({ advertiserStats }: { advertiserStats: DeepPartia status={getStatus(isAddressVerified)} variant={getVariant(isAddressVerified)} /> - {isPhoneNumberVerificationEnabled && ( + {isPhoneNumberVerificationEnabled && isMyProfile && ( ({ useGetPhoneNumberVerification: jest.fn(() => mockUseGetPhoneNumberVerification), })); +jest.mock('@/utils', () => ({ + ...jest.requireActual('@/utils'), + getCurrentRoute: jest.fn(() => 'my-profile'), +})); + const mockProps = { advertiserStats: { isAddressVerified: false,