From 8664cb59a1f659258ce4bcefd5233c1675e5e369 Mon Sep 17 00:00:00 2001 From: Sui Sin <103026762+suisin-deriv@users.noreply.github.com> Date: Fri, 10 Jan 2025 21:40:04 +0800 Subject: [PATCH] [TRAH5082] Suisin/trah5082/change traders hub button url based on ff (#17916) * chore: open new tab for options and cfds in hub when user has wallets account * chore: only to add it in wallets account switcher * chore: fix build fail * chore: revert TContractInfo auto convert * chore: change to have redirection logic on tradershub page itself * chore: change taxResidence to citizen * chore: update redirection logic and add hooks for checking hub redirection * chore: revert auto correct TContractInfo * chore: revert AppContent and account-switcher-wallet logic * chore: if modal is open in tradershub we dont redirect user to low-code * chore: fix failing testcase and revert TContractInfo * chore: display blank screen in wallets for hub enabled countries * chore: fix build failing issue * chore: fix code based on comments * chore: update to use process.env.NODE_ENV based on comment * chore: update logic redirection to check either trading_hub or GB value is true * chore: fix redirection to staging-hub when clicking on cfds button * chore: fix redirection before clicking on Get started --- packages/api-v2/src/hooks/index.ts | 2 + .../src/hooks/useGrowthbookGetFeatureValue.ts | 41 +++++++++++++++++++ .../src/hooks/useIsHubRedirectionEnabled.ts | 34 +++++++++++++++ .../__tests__/platform-dropdown.spec.tsx | 15 +++++-- .../Layout/Header/platform-dropdown.jsx | 12 +++++- .../account-switcher-wallet-mobile.spec.tsx | 7 +++- .../account-switcher-wallet.spec.tsx | 11 ++++- .../account-switcher-wallet-mobile.tsx | 14 +++++-- .../account-switcher-wallet.tsx | 14 +++++-- .../ConfirmEmailModal/confirm-email-modal.tsx | 7 +++- .../LinkExpiredModal/link-expired-modal.tsx | 13 ++++-- .../wallets-upgrade-completed-modal.tsx | 10 ++++- .../src/App/Containers/Redirect/redirect.jsx | 18 ++++++-- .../reset-password-modal.tsx | 5 ++- .../RootComponent/root-component.jsx | 19 +++++++-- packages/core/src/Stores/client-store.js | 7 ++++ packages/core/src/Stores/ui-store.js | 6 +++ packages/stores/src/mockStore.ts | 2 + packages/stores/types.ts | 2 + packages/wallets/src/App.tsx | 3 ++ packages/wallets/src/AppContent.tsx | 9 +++- .../__tests__/ModalStepWrapper.spec.tsx | 16 +++++--- .../ModalProvider/ModalProvider.tsx | 9 ++++ .../__tests__/WalletError.spec.tsx | 22 +++++++--- .../WalletsAddMoreCardBanner.spec.tsx | 18 ++++++++ .../WalletSuccessChangeMT5Password.spec.tsx | 10 ++++- .../__tests__/CryptoTransaction.spec.tsx | 8 ++++ .../__tests__/TransactionsPendingRow.spec.tsx | 8 ++++ .../TransactionsPendingRowField.spec.tsx | 32 +++++++++++---- .../AddedCTraderAccountsList.spec.tsx | 8 ++++ .../AvailableCtraderAccountsList.spec.tsx | 15 ++++++- .../__tests__/AddedMT5AccountsList.spec.tsx | 10 ++++- .../AddedDxtradeAccountsList.spec.tsx | 8 ++++ .../__tests__/CtraderSuccessModal.spec.tsx | 8 ++++ .../DxtradeEnterPasswordModal.spec.tsx | 10 +++++ .../__tests__/TradingPlatformStatus.spec.tsx | 32 +++++++++++---- packages/wallets/src/routes/Router.tsx | 8 +++- .../WalletsListingRoute.tsx | 10 ++++- .../__tests__/WalletsListingRoute.spec.tsx | 10 ++--- 39 files changed, 421 insertions(+), 72 deletions(-) create mode 100644 packages/api-v2/src/hooks/useGrowthbookGetFeatureValue.ts create mode 100644 packages/api-v2/src/hooks/useIsHubRedirectionEnabled.ts diff --git a/packages/api-v2/src/hooks/index.ts b/packages/api-v2/src/hooks/index.ts index 956afb2de38a..d8f7d43ec5c7 100644 --- a/packages/api-v2/src/hooks/index.ts +++ b/packages/api-v2/src/hooks/index.ts @@ -40,9 +40,11 @@ export { default as useDynamicLeverage } from './useDynamicLeverage'; export { default as useExchangeRateSubscription } from './useExchangeRateSubscription'; export { default as useGetAccountStatus } from './useGetAccountStatus'; export { default as useGetExchangeRate } from './useGetExchangeRate'; +export { default as useGrowthbookGetFeatureValue } from './useGrowthbookGetFeatureValue'; export { default as useGrowthbookIsOn } from './useGrowthbookIsOn'; export { default as useIdentityDocumentVerificationAdd } from './useIdentityDocumentVerificationAdd'; export { default as useIsEuRegion } from './useIsEuRegion'; +export { default as useIsHubRedirectionEnabled } from './useIsHubRedirectionEnabled'; export { default as useJurisdictionStatus } from './useJurisdictionStatus'; export { default as useLandingCompany } from './useLandingCompany'; export { default as useMT5AccountsList } from './useMT5AccountsList'; diff --git a/packages/api-v2/src/hooks/useGrowthbookGetFeatureValue.ts b/packages/api-v2/src/hooks/useGrowthbookGetFeatureValue.ts new file mode 100644 index 000000000000..e82c379cc031 --- /dev/null +++ b/packages/api-v2/src/hooks/useGrowthbookGetFeatureValue.ts @@ -0,0 +1,41 @@ +import { useEffect, useState } from 'react'; +import { useIsMounted } from 'usehooks-ts'; + +import { getFeatureFlag } from '@deriv/utils'; +import { Analytics } from '@deriv-com/analytics'; + +interface UseGrowthbookGetFeatureValueArgs { + featureFlag: string; + defaultValue?: T; +} + +const useGrowthbookGetFeatureValue = ({ + featureFlag, + defaultValue, +}: UseGrowthbookGetFeatureValueArgs) => { + const resolvedDefaultValue: T = defaultValue !== undefined ? defaultValue : (false as T); + const [featureFlagValue, setFeatureFlagValue] = useState(false); + const [isGBLoaded, setIsGBLoaded] = useState(false); + const isMounted = useIsMounted(); + + // Required for debugging Growthbook, this will be removed after this is added in the Analytics directly. + if (typeof window !== 'undefined') { + window.Analytics = Analytics; + } + + useEffect(() => { + const fetchFeatureFlag = async () => { + const is_enabled = await getFeatureFlag(featureFlag, resolvedDefaultValue); + if (isMounted()) { + setFeatureFlagValue(is_enabled); + setIsGBLoaded(true); + } + }; + + fetchFeatureFlag(); + }, [featureFlag, resolvedDefaultValue, isMounted]); + + return [featureFlagValue, isGBLoaded]; +}; + +export default useGrowthbookGetFeatureValue; diff --git a/packages/api-v2/src/hooks/useIsHubRedirectionEnabled.ts b/packages/api-v2/src/hooks/useIsHubRedirectionEnabled.ts new file mode 100644 index 000000000000..4690ed14ed0e --- /dev/null +++ b/packages/api-v2/src/hooks/useIsHubRedirectionEnabled.ts @@ -0,0 +1,34 @@ +import useClientCountry from './useClientCountry'; +import useGrowthbookGetFeatureValue from './useGrowthbookGetFeatureValue'; +import useSettings from './useSettings'; + +type THubEnabledCountryList = { + hub_enabled_country_list: string[]; +}; + +const useIsHubRedirectionEnabled = () => { + const [hubEnabledCountryList] = useGrowthbookGetFeatureValue({ + featureFlag: 'hub_enabled_country_list', + }); + const { data: clientCountry } = useClientCountry(); + const { data: accountSettings } = useSettings(); + const { citizen } = accountSettings; + + const isHubRedirectionEnabled = + typeof hubEnabledCountryList === 'object' && + hubEnabledCountryList !== null && + Array.isArray((hubEnabledCountryList as THubEnabledCountryList).hub_enabled_country_list) && + citizen && + (hubEnabledCountryList as THubEnabledCountryList).hub_enabled_country_list.includes(citizen); + + const isChangingToHubAppId = + typeof hubEnabledCountryList === 'object' && + hubEnabledCountryList !== null && + Array.isArray((hubEnabledCountryList as THubEnabledCountryList).hub_enabled_country_list) && + clientCountry && + (hubEnabledCountryList as THubEnabledCountryList).hub_enabled_country_list.includes(clientCountry); + + return { isHubRedirectionEnabled, isChangingToHubAppId }; +}; + +export default useIsHubRedirectionEnabled; diff --git a/packages/core/src/App/Components/Layout/Header/__tests__/platform-dropdown.spec.tsx b/packages/core/src/App/Components/Layout/Header/__tests__/platform-dropdown.spec.tsx index aca622a976bd..09103df6086d 100644 --- a/packages/core/src/App/Components/Layout/Header/__tests__/platform-dropdown.spec.tsx +++ b/packages/core/src/App/Components/Layout/Header/__tests__/platform-dropdown.spec.tsx @@ -17,6 +17,13 @@ type TMockPlatformDropdown = { }[]; }; +jest.mock('@deriv/hooks', () => ({ + ...jest.requireActual('@deriv/hooks'), + useIsHubRedirectionEnabled: () => ({ + isHubRedirectionEnabled: false, + }), +})); + const history = createBrowserHistory(); const store = mockStore({}); @@ -81,19 +88,19 @@ describe('PlatformDropdown component', () => { expect(screen.getByTestId('dt_platform_dropdown_link')).toBeInTheDocument(); expect(screen.getByText(tradershub_redirect)).toBeInTheDocument(); }); - it('should update URL when clicking on another (non-selected) platform', () => { + it('should update URL when clicking on another (non-selected) platform', async () => { history.push(routes.bot); render(); - userEvent.click(screen.getByText(dtrader_description)); + await userEvent.click(screen.getByText(dtrader_description)); expect(history.location.pathname).toBe(routes.trade); expect(history.location.search).toBe(''); }); - it('should not update URL when clicking on an already selected platform', () => { + it('should not update URL when clicking on an already selected platform', async () => { history.push(routes.trade + dtrader_url_params); render(); - userEvent.click(screen.getByText(dtrader_description)); + await userEvent.click(screen.getByText(dtrader_description)); expect(history.location.pathname).toBe(routes.trade); expect(history.location.search).toBe(dtrader_url_params); }); diff --git a/packages/core/src/App/Components/Layout/Header/platform-dropdown.jsx b/packages/core/src/App/Components/Layout/Header/platform-dropdown.jsx index 9bfca8bc4492..daf5d2659828 100644 --- a/packages/core/src/App/Components/Layout/Header/platform-dropdown.jsx +++ b/packages/core/src/App/Components/Layout/Header/platform-dropdown.jsx @@ -1,12 +1,14 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Div100vhContainer, Icon, useOnClickOutside, Text } from '@deriv/components'; -import { routes, getActivePlatform } from '@deriv/shared'; +import { routes, getActivePlatform, platforms } from '@deriv/shared'; import { BinaryLink } from 'App/Components/Routes'; import 'Sass/app/_common/components/platform-dropdown.scss'; import { Localize } from '@deriv/translations'; import { useHistory } from 'react-router'; import { useDevice } from '@deriv-com/ui'; +import { useIsHubRedirectionEnabled } from '@deriv/hooks'; +import { useStore } from '@deriv/stores'; const PlatformBox = ({ platform: { icon, description } }) => ( @@ -50,12 +52,20 @@ const PlatformDropdownContent = ({ platform, app_routing_history }) => { const PlatformDropdown = ({ app_routing_history, closeDrawer, platform_config, setTogglePlatformType }) => { const history = useHistory(); const { isDesktop } = useDevice(); + const { isHubRedirectionEnabled } = useIsHubRedirectionEnabled(); + const { client } = useStore(); + const { account_settings } = client; + const { trading_hub } = account_settings; const TradersHubRedirect = () => { return (
{ + if (isHubRedirectionEnabled || !!trading_hub) { + window.location.assign(platforms.tradershub_os.url); + return; + } if (!isDesktop) { history.push(routes.traders_hub); setTogglePlatformType('cfd'); diff --git a/packages/core/src/App/Containers/AccountSwitcherWallet/__tests__/account-switcher-wallet-mobile.spec.tsx b/packages/core/src/App/Containers/AccountSwitcherWallet/__tests__/account-switcher-wallet-mobile.spec.tsx index 76fd6e8397dc..4cacfb780de0 100644 --- a/packages/core/src/App/Containers/AccountSwitcherWallet/__tests__/account-switcher-wallet-mobile.spec.tsx +++ b/packages/core/src/App/Containers/AccountSwitcherWallet/__tests__/account-switcher-wallet-mobile.spec.tsx @@ -9,6 +9,9 @@ jest.mock('@deriv/hooks', () => ({ useWalletAccountsList: jest.fn(() => ({ data: [{ loginid: 'CR007', dtrade_loginid: 'CR008' }], })), + useIsHubRedirectionEnabled: jest.fn(() => ({ + isHubRedirectionEnabled: false, + })), })); jest.mock('react-router', () => ({ @@ -93,7 +96,7 @@ describe('AccountSwitcherWalletMobile', () => { expect(screen.getByText('AccountSwitcherWalletList')).toBeInTheDocument(); }); - it('should toggle the switcher on footer click', () => { + it('should toggle the switcher on footer click', async () => { const store = mockStore({ client: { accounts: { @@ -107,7 +110,7 @@ describe('AccountSwitcherWalletMobile', () => { }); render(, { wrapper: wrapper(store) }); const footer = screen.getByText('Looking for CFDs? Go to Trader’s Hub'); - userEvent.click(footer); + await userEvent.click(footer); expect(props.toggle).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/core/src/App/Containers/AccountSwitcherWallet/__tests__/account-switcher-wallet.spec.tsx b/packages/core/src/App/Containers/AccountSwitcherWallet/__tests__/account-switcher-wallet.spec.tsx index 65791d58c90d..a497e8fca0e1 100644 --- a/packages/core/src/App/Containers/AccountSwitcherWallet/__tests__/account-switcher-wallet.spec.tsx +++ b/packages/core/src/App/Containers/AccountSwitcherWallet/__tests__/account-switcher-wallet.spec.tsx @@ -11,6 +11,13 @@ jest.mock('react-router', () => ({ }), })); +jest.mock('@deriv/hooks', () => ({ + ...jest.requireActual('@deriv/hooks'), + useIsHubRedirectionEnabled: () => ({ + isHubRedirectionEnabled: false, + }), +})); + jest.mock('../account-switcher-wallet-list', () => ({ AccountSwitcherWalletList: () =>
AccountSwitcherWalletList
, })); @@ -74,12 +81,12 @@ describe('AccountSwitcherWalletComponent', () => { expect(screen.getByText('AccountSwitcherWalletList')).toBeInTheDocument(); }); - it('should toggle the switcher on button click', () => { + it('should toggle the switcher on button click', async () => { const mock = mockStore({}); render(, { wrapper: wrapper(mock) }); const button = screen.getByTestId('dt_go_to_arrow'); - userEvent.click(button); + await userEvent.click(button); expect(props.toggle).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/core/src/App/Containers/AccountSwitcherWallet/account-switcher-wallet-mobile.tsx b/packages/core/src/App/Containers/AccountSwitcherWallet/account-switcher-wallet-mobile.tsx index 3611639f2548..cf77444b0fce 100644 --- a/packages/core/src/App/Containers/AccountSwitcherWallet/account-switcher-wallet-mobile.tsx +++ b/packages/core/src/App/Containers/AccountSwitcherWallet/account-switcher-wallet-mobile.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { useHistory } from 'react-router'; import { Button, Icon, MobileDialog, Text } from '@deriv/components'; -import { routes } from '@deriv/shared'; +import { platforms, routes } from '@deriv/shared'; import { Localize } from '@deriv/translations'; import { AccountSwitcherWalletList } from './account-switcher-wallet-list'; -import { useIsRtl, useStoreWalletAccountsList } from '@deriv/hooks'; -import { observer } from '@deriv/stores'; +import { useIsHubRedirectionEnabled, useIsRtl, useStoreWalletAccountsList } from '@deriv/hooks'; +import { observer, useStore } from '@deriv/stores'; import './account-switcher-wallet-mobile.scss'; type TAccountSwitcherWalletMobile = { @@ -18,14 +18,22 @@ export const AccountSwitcherWalletMobile = observer(({ is_visible, toggle, login const history = useHistory(); const isRtl = useIsRtl(); const { data: wallet_list } = useStoreWalletAccountsList(); + const { client } = useStore(); + const { account_settings } = client; + const { trading_hub } = account_settings; const dtrade_account_wallets = wallet_list?.filter(wallet => wallet.dtrade_loginid); + const { isHubRedirectionEnabled } = useIsHubRedirectionEnabled(); const closeAccountsDialog = React.useCallback(() => { toggle(false); }, [toggle]); const handleTradersHubRedirect = () => { + if (isHubRedirectionEnabled || !!trading_hub) { + window.location.assign(platforms.tradershub_os.url); + return; + } closeAccountsDialog(); history.push(routes.traders_hub); }; diff --git a/packages/core/src/App/Containers/AccountSwitcherWallet/account-switcher-wallet.tsx b/packages/core/src/App/Containers/AccountSwitcherWallet/account-switcher-wallet.tsx index 8ed4182b10c1..3c20521b8c60 100644 --- a/packages/core/src/App/Containers/AccountSwitcherWallet/account-switcher-wallet.tsx +++ b/packages/core/src/App/Containers/AccountSwitcherWallet/account-switcher-wallet.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { useHistory } from 'react-router'; import { Icon, Text, ThemedScrollbars, useOnClickOutside } from '@deriv/components'; -import { routes } from '@deriv/shared'; -import { observer } from '@deriv/stores'; +import { platforms, routes } from '@deriv/shared'; +import { observer, useStore } from '@deriv/stores'; import { Localize } from '@deriv/translations'; -import { useStoreWalletAccountsList } from '@deriv/hooks'; +import { useIsHubRedirectionEnabled, useStoreWalletAccountsList } from '@deriv/hooks'; import { AccountSwitcherWalletList } from './account-switcher-wallet-list'; import './account-switcher-wallet.scss'; @@ -18,8 +18,12 @@ export const AccountSwitcherWallet = observer(({ is_visible, toggle }: TAccountS const dtrade_account_wallets = wallet_list?.filter(wallet => wallet.dtrade_loginid); const history = useHistory(); + const { client } = useStore(); + const { account_settings } = client; + const { trading_hub } = account_settings; const wrapper_ref = React.useRef(null); + const { isHubRedirectionEnabled } = useIsHubRedirectionEnabled(); const validateClickOutside = (event: MouseEvent) => { const checkAllParentNodes = (node: HTMLElement): boolean => { @@ -39,6 +43,10 @@ export const AccountSwitcherWallet = observer(({ is_visible, toggle }: TAccountS useOnClickOutside(wrapper_ref, closeAccountsDialog, validateClickOutside); const handleTradersHubRedirect = async () => { + if (isHubRedirectionEnabled || !!trading_hub) { + window.location.assign(platforms.tradershub_os.url); + return; + } closeAccountsDialog(); history.push(routes.traders_hub); }; diff --git a/packages/core/src/App/Containers/ConfirmEmailModal/confirm-email-modal.tsx b/packages/core/src/App/Containers/ConfirmEmailModal/confirm-email-modal.tsx index e43da406c2f0..1af01df13dd8 100644 --- a/packages/core/src/App/Containers/ConfirmEmailModal/confirm-email-modal.tsx +++ b/packages/core/src/App/Containers/ConfirmEmailModal/confirm-email-modal.tsx @@ -22,7 +22,7 @@ export const ConfirmEmailModal = observer( const [is_modal_open, setIsModalOpen] = React.useState(is_open); const { client } = useStore(); - const { verification_code, setVerificationCode } = client; + const { verification_code, setVerificationCode, setPreventRedirectToHub } = client; const handleSubmit = () => { const api_request: TSocketRequest<'change_email'> = { @@ -57,7 +57,10 @@ export const ConfirmEmailModal = observer( return ( setIsSendEmailModalOpen(false)} + onClose={() => { + setIsSendEmailModalOpen(false); + setPreventRedirectToHub(false); + }} identifier_title={'Change_Email'} onClickSendEmail={resendEmail} has_live_chat diff --git a/packages/core/src/App/Containers/LinkExpiredModal/link-expired-modal.tsx b/packages/core/src/App/Containers/LinkExpiredModal/link-expired-modal.tsx index 8ba00217b65e..39a36fc497ac 100644 --- a/packages/core/src/App/Containers/LinkExpiredModal/link-expired-modal.tsx +++ b/packages/core/src/App/Containers/LinkExpiredModal/link-expired-modal.tsx @@ -9,7 +9,8 @@ import { Localize, localize } from '@deriv/translations'; import EmailResent from './email-resent'; const LinkExpiredModal = observer(() => { - const { ui } = useStore(); + const { ui, client } = useStore(); + const { setPreventRedirectToHub } = client; const { enableApp, disableApp, is_link_expired_modal_visible: is_visible, toggleLinkExpiredModal } = ui; const { send, error: verify_error, data: verify_data } = useVerifyEmail('reset_password'); @@ -60,7 +61,10 @@ const LinkExpiredModal = observer(() => { enableApp={enableApp} title={is_email_sent ? '' : localize('Link expired')} has_close_icon - onConfirm={() => toggleLinkExpiredModal(false)} + onConfirm={() => { + toggleLinkExpiredModal(false); + setPreventRedirectToHub(false); + }} >
{is_email_sent ? ( @@ -94,7 +98,10 @@ const LinkExpiredModal = observer(() => { toggleLinkExpiredModal(false)} + onCancel={() => { + toggleLinkExpiredModal(false); + setPreventRedirectToHub(false); + }} is_disabled={!values.email || !!errors.email || isSubmitting} is_loading={isSubmitting} label={localize('Resend email')} diff --git a/packages/core/src/App/Containers/Modals/wallets-upgrade-completed-modal/wallets-upgrade-completed-modal.tsx b/packages/core/src/App/Containers/Modals/wallets-upgrade-completed-modal/wallets-upgrade-completed-modal.tsx index 691967745825..e31304638034 100644 --- a/packages/core/src/App/Containers/Modals/wallets-upgrade-completed-modal/wallets-upgrade-completed-modal.tsx +++ b/packages/core/src/App/Containers/Modals/wallets-upgrade-completed-modal/wallets-upgrade-completed-modal.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; import Cookies from 'js-cookie'; import { Button, Icon, MobileDialog, Modal, Text } from '@deriv/components'; @@ -9,13 +9,19 @@ import './wallets-upgrade-completed-modal.scss'; const WalletsUpgradeCompletedModal = observer(() => { const history = useHistory(); - const { ui } = useStore(); + const { client, ui } = useStore(); const { is_mobile } = ui; + const { setPreventRedirectToHub } = client; const [isOpen, setIsOpen] = useState(true); + useEffect(() => { + setPreventRedirectToHub(true); + }, []); + const handleClose = () => { setIsOpen(false); Cookies.remove('recent_wallets_migration'); + setPreventRedirectToHub(false); history.push(routes.traders_hub); }; diff --git a/packages/core/src/App/Containers/Redirect/redirect.jsx b/packages/core/src/App/Containers/Redirect/redirect.jsx index b0a8886f4a49..52c2f8a87b8f 100644 --- a/packages/core/src/App/Containers/Redirect/redirect.jsx +++ b/packages/core/src/App/Containers/Redirect/redirect.jsx @@ -13,8 +13,16 @@ const Redirect = observer(() => { const history = useHistory(); const { client, ui } = useStore(); - const { currency, has_wallet, is_logged_in, is_logging_in, setNewEmail, setVerificationCode, verification_code } = - client; + const { + currency, + has_wallet, + is_logged_in, + is_logging_in, + setNewEmail, + setVerificationCode, + verification_code, + setPreventRedirectToHub, + } = client; const { openRealAccountSignup, @@ -93,6 +101,7 @@ const Redirect = observer(() => { break; } case 'reset_password': { + setPreventRedirectToHub(true); toggleResetPasswordModal(true); break; } @@ -109,15 +118,18 @@ const Redirect = observer(() => { setVerificationCode(request_email_code, action_param); sessionStorage.removeItem('request_email_code'); } + setPreventRedirectToHub(true); toggleResetEmailModal(true); } break; } case 'social_email_change': { + setPreventRedirectToHub(true); toggleResetPasswordModal(true); break; } case 'system_email_change': { + setPreventRedirectToHub(true); toggleUpdateEmailModal(true); break; } @@ -173,7 +185,7 @@ const Redirect = observer(() => { redirected_to_route = true; } } - + setPreventRedirectToHub(true); setResetTradingPasswordModalOpen(true); break; } diff --git a/packages/core/src/App/Containers/ResetPasswordModal/reset-password-modal.tsx b/packages/core/src/App/Containers/ResetPasswordModal/reset-password-modal.tsx index 13d52bbfbe3f..c926f2d3ac52 100644 --- a/packages/core/src/App/Containers/ResetPasswordModal/reset-password-modal.tsx +++ b/packages/core/src/App/Containers/ResetPasswordModal/reset-password-modal.tsx @@ -14,7 +14,7 @@ type TResetPasswordModalValues = { const ResetPasswordModal = observer(() => { const { ui, client } = useStore(); - const { logout: logoutClient, verification_code, setVerificationCode } = client; + const { logout: logoutClient, verification_code, setVerificationCode, setPreventRedirectToHub } = client; const { disableApp, enableApp, @@ -46,7 +46,7 @@ const ResetPasswordModal = observer(() => { } return; } - + setPreventRedirectToHub(false); actions.setStatus({ reset_complete: true }); logoutClient().then(() => { redirectToLogin(false, getLanguage(), false); @@ -93,6 +93,7 @@ const ResetPasswordModal = observer(() => { const reset_initial_values: TResetPasswordModalValues = { password: '' }; const closeResetPasswordModal = () => { + setPreventRedirectToHub(false); toggleResetPasswordModal(false); removeActionParam('reset_password'); }; diff --git a/packages/core/src/App/Containers/RootComponent/root-component.jsx b/packages/core/src/App/Containers/RootComponent/root-component.jsx index d175670e45d1..8a1cfda5e7df 100644 --- a/packages/core/src/App/Containers/RootComponent/root-component.jsx +++ b/packages/core/src/App/Containers/RootComponent/root-component.jsx @@ -1,6 +1,6 @@ -import React from 'react'; +import React, { useEffect } from 'react'; -import { useOauth2 } from '@deriv/hooks'; +import { useIsHubRedirectionEnabled, useOauth2 } from '@deriv/hooks'; import { moduleLoader } from '@deriv/shared'; import { observer, useStore } from '@deriv/stores'; @@ -25,13 +25,25 @@ const RootComponent = observer(props => { setIsWalletsOnboardingTourGuideVisible, notification_messages_ui, } = ui; - const { has_wallet, logout } = client; + const { has_wallet, logout, account_settings, prevent_redirect_to_hub } = client; + const { trading_hub } = account_settings; const { oAuthLogout } = useOauth2({ handleLogout: logout }); const onWalletsOnboardingTourGuideCloseHandler = () => { setIsWalletsOnboardingTourGuideVisible(false); }; + const { isHubRedirectionEnabled } = useIsHubRedirectionEnabled(); + + const PRODUCTION_REDIRECT_URL = 'https://hub.deriv.com/tradershub/options'; + const STAGING_REDIRECT_URL = 'https://staging-hub.deriv.com/tradershub/options'; + + useEffect(() => { + if (((isHubRedirectionEnabled && has_wallet) || !!trading_hub) && !prevent_redirect_to_hub) { + const redirectUrl = process.env.NODE_ENV === 'production' ? PRODUCTION_REDIRECT_URL : STAGING_REDIRECT_URL; + window.location.assign(redirectUrl); + } + }, [isHubRedirectionEnabled, has_wallet, trading_hub, prevent_redirect_to_hub]); return has_wallet ? ( { }} notificationMessagesUi={notification_messages_ui} onWalletsOnboardingTourGuideCloseHandler={onWalletsOnboardingTourGuideCloseHandler} + isHubRedirectionEnabled={isHubRedirectionEnabled || !!trading_hub} /> ) : ( diff --git a/packages/core/src/Stores/client-store.js b/packages/core/src/Stores/client-store.js index afc5cc639261..e5b25bcb0b08 100644 --- a/packages/core/src/Stores/client-store.js +++ b/packages/core/src/Stores/client-store.js @@ -114,6 +114,7 @@ export default class ClientStore extends BaseStore { amount_dxtrade: undefined, currency: '', }; + prevent_redirect_to_hub = false; verification_code = { signup: '', @@ -239,6 +240,7 @@ export default class ClientStore extends BaseStore { dxtrade_trading_servers: observable, prev_real_account_loginid: observable, prev_account_type: observable, + prevent_redirect_to_hub: observable, phone_settings: observable, is_already_attempted: observable, is_p2p_enabled: observable, @@ -331,6 +333,7 @@ export default class ClientStore extends BaseStore { setPreferredLanguage: action.bound, setCookieAccount: action.bound, setCFDScore: action.bound, + setPreventRedirectToHub: action.bound, updateSelfExclusion: action.bound, responsePayoutCurrencies: action.bound, responseAuthorize: action.bound, @@ -927,6 +930,10 @@ export default class ClientStore extends BaseStore { } }; + setPreventRedirectToHub = value => { + this.prevent_redirect_to_hub = value; + }; + getIsMarketTypeMatching = (account, market_type) => { if (market_type === 'synthetic') { return account.market_type === market_type || account.market_type === 'gaming'; diff --git a/packages/core/src/Stores/ui-store.js b/packages/core/src/Stores/ui-store.js index f55db96fdaed..53a4ac4e192e 100644 --- a/packages/core/src/Stores/ui-store.js +++ b/packages/core/src/Stores/ui-store.js @@ -792,6 +792,9 @@ export default class UIStore extends BaseStore { } toggleResetEmailModal(state_change = !this.is_reset_email_modal_visible) { + if (!state_change) { + this.root_store.client.setPreventRedirectToHub(false); + } this.is_reset_email_modal_visible = state_change; } @@ -800,6 +803,9 @@ export default class UIStore extends BaseStore { } setResetTradingPasswordModalOpen(is_reset_trading_password_modal_visible) { + if (!is_reset_trading_password_modal_visible) { + this.root_store.client.setPreventRedirectToHub(false); + } this.is_reset_trading_password_modal_visible = is_reset_trading_password_modal_visible; } diff --git a/packages/stores/src/mockStore.ts b/packages/stores/src/mockStore.ts index 8cb09c7b748f..79951a3aaa4e 100644 --- a/packages/stores/src/mockStore.ts +++ b/packages/stores/src/mockStore.ts @@ -198,6 +198,8 @@ const mock = (): TStores & { is_mock: boolean } => { trading_platform_dxtrade_password_reset: '', trading_platform_mt5_password_reset: '', }, + prevent_redirect_to_hub: false, + setPreventRedirectToHub: jest.fn(), email: '', fetchStatesList: jest.fn(), setVerificationCode: jest.fn(), diff --git a/packages/stores/types.ts b/packages/stores/types.ts index 51d7a7419ae9..48991630bfdf 100644 --- a/packages/stores/types.ts +++ b/packages/stores/types.ts @@ -540,6 +540,8 @@ export type TClientStore = { trading_platform_accounts: DetailsOfEachMT5Loginid[]; }) => DetailsOfEachMT5Loginid[]; standpoint: TStandPoint; + prevent_redirect_to_hub: boolean; + setPreventRedirectToHub: (value: boolean) => void; setAccountStatus: (status?: GetAccountStatus) => void; setBalanceOtherAccounts: (balance: number) => void; selectCurrency: (currency: string) => void; diff --git a/packages/wallets/src/App.tsx b/packages/wallets/src/App.tsx index 6bf6cf2f1a1b..12a5ac90eba2 100644 --- a/packages/wallets/src/App.tsx +++ b/packages/wallets/src/App.tsx @@ -11,6 +11,7 @@ import './styles/fonts.scss'; import './index.scss'; type TProps = { + isHubRedirectionEnabled: boolean; isWalletsOnboardingTourGuideVisible: boolean; logout: () => Promise; notificationMessagesUi: (props?: { @@ -25,6 +26,7 @@ type TProps = { const LazyWalletTourGuide = lazy(() => import('./components/WalletTourGuide/WalletTourGuide')); const App: React.FC = ({ + isHubRedirectionEnabled, isWalletsOnboardingTourGuideVisible, logout, notificationMessagesUi: Notifications, @@ -51,6 +53,7 @@ const App: React.FC = ({ {!isWalletsOnboardingTourGuideVisible && Notifications && } diff --git a/packages/wallets/src/AppContent.tsx b/packages/wallets/src/AppContent.tsx index 55b63493d832..8125a3afa573 100644 --- a/packages/wallets/src/AppContent.tsx +++ b/packages/wallets/src/AppContent.tsx @@ -9,11 +9,16 @@ import { TLanguageType } from './types'; import './AppContent.scss'; type AppContentProps = { + isHubRedirectionEnabled: boolean; isWalletsOnboardingTourGuideVisible: boolean; setPreferredLanguage: (language: TLanguageType | null) => void; }; -const AppContent: React.FC = ({ isWalletsOnboardingTourGuideVisible, setPreferredLanguage }) => { +const AppContent: React.FC = ({ + isHubRedirectionEnabled, + isWalletsOnboardingTourGuideVisible, + setPreferredLanguage, +}) => { const { isSubscribed, subscribeToAllBalance, unsubscribeFromAllBalance } = useAllBalanceSubscription(); const { data: derivAccountList } = useDerivAccountsList(); const previousDerivAccountListLengthRef = useRef(0); @@ -74,7 +79,7 @@ const AppContent: React.FC = ({ isWalletsOnboardingTourGuideVis ref={appRef} >
- +
); }; diff --git a/packages/wallets/src/components/Base/ModalStepWrapper/__tests__/ModalStepWrapper.spec.tsx b/packages/wallets/src/components/Base/ModalStepWrapper/__tests__/ModalStepWrapper.spec.tsx index 1323899bc1df..2d2d1dc9b2dd 100644 --- a/packages/wallets/src/components/Base/ModalStepWrapper/__tests__/ModalStepWrapper.spec.tsx +++ b/packages/wallets/src/components/Base/ModalStepWrapper/__tests__/ModalStepWrapper.spec.tsx @@ -3,6 +3,8 @@ import { render, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ModalProvider } from '../../../ModalProvider'; import ModalStepWrapper from '../ModalStepWrapper'; +import { APIProvider } from '@deriv/api-v2'; +import WalletsAuthProvider from '../../../../AuthProvider'; const mockhideFn = jest.fn(); jest.mock('../../../ModalProvider', () => ({ @@ -19,11 +21,15 @@ beforeEach(() => { describe('ModalStepWrapper', () => { const MockComponent = (props: React.ComponentProps) => ( - - -
test
-
-
+ + + + +
test
+
+
+
+
); it('should render ModalStepWrapper on default values', () => { diff --git a/packages/wallets/src/components/ModalProvider/ModalProvider.tsx b/packages/wallets/src/components/ModalProvider/ModalProvider.tsx index 267bdfefa34b..672ddb1af2ae 100644 --- a/packages/wallets/src/components/ModalProvider/ModalProvider.tsx +++ b/packages/wallets/src/components/ModalProvider/ModalProvider.tsx @@ -4,6 +4,7 @@ import { useHistory } from 'react-router-dom'; import { useOnClickOutside } from 'usehooks-ts'; import { useDevice } from '@deriv-com/ui'; import { THooks, TMarketTypes, TPlatforms } from '../../types'; +import { useIsHubRedirectionEnabled, useSettings } from '@deriv/api-v2'; type TModalState = { accountId?: string; @@ -46,6 +47,9 @@ const ModalProvider = ({ children }: React.PropsWithChildren) => { const [modalState, setModalState] = useState>(new Map()); const { isDesktop } = useDevice(); const history = useHistory(); + const { isHubRedirectionEnabled } = useIsHubRedirectionEnabled(); + const { data: accountSettings } = useSettings(); + const { trading_hub: tradingHub } = accountSettings; const rootRef = useRef(document.getElementById('wallets_modal_root')); const rootHeaderRef = useRef(document.getElementById('wallets_modal_show_header_root')); @@ -83,6 +87,11 @@ const ModalProvider = ({ children }: React.PropsWithChildren) => { ...prevModalOptions, rootRef: undefined, })); + // We need to add this check here because wallets account is coming from Low-Code tradershub. + // This condition is to reload the page when the modal is closed. + if (isHubRedirectionEnabled || !!tradingHub) { + window.location.reload(); + } }; const onClickOutsideHandler = () => diff --git a/packages/wallets/src/components/WalletError/__tests__/WalletError.spec.tsx b/packages/wallets/src/components/WalletError/__tests__/WalletError.spec.tsx index 247533794a25..e499b7bc2d94 100644 --- a/packages/wallets/src/components/WalletError/__tests__/WalletError.spec.tsx +++ b/packages/wallets/src/components/WalletError/__tests__/WalletError.spec.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { ModalProvider } from '../../ModalProvider'; import WalletError from '../WalletError'; +import { APIProvider } from '@deriv/api-v2'; +import WalletsAuthProvider from '../../../AuthProvider'; jest.mock('@deriv-com/ui', () => ({ ...jest.requireActual('@deriv-com/ui'), @@ -22,9 +24,13 @@ jest.mock('../../ModalProvider', () => ({ describe('WalletError', () => { it('should show error message and the title', () => { render( - - - + + + + + + + ); expect(screen.getByText('Error message')).toBeInTheDocument(); expect(screen.getByText('Something went wrong!')).toBeInTheDocument(); @@ -32,9 +38,13 @@ describe('WalletError', () => { it('should call hide modal when close button is clicked', () => { render( - - - + + + + + + + ); const closeButton = screen.getByRole('button', { name: 'Close' }); closeButton.click(); diff --git a/packages/wallets/src/components/WalletsAddMoreCardBanner/__tests__/WalletsAddMoreCardBanner.spec.tsx b/packages/wallets/src/components/WalletsAddMoreCardBanner/__tests__/WalletsAddMoreCardBanner.spec.tsx index f0337c79dc42..7de75e29ed20 100644 --- a/packages/wallets/src/components/WalletsAddMoreCardBanner/__tests__/WalletsAddMoreCardBanner.spec.tsx +++ b/packages/wallets/src/components/WalletsAddMoreCardBanner/__tests__/WalletsAddMoreCardBanner.spec.tsx @@ -6,6 +6,8 @@ import { useIsEuRegion, useLandingCompany, useWalletAccountsList, + useIsHubRedirectionEnabled, + useSettings, } from '@deriv/api-v2'; import { Analytics } from '@deriv-com/analytics'; import { useDevice } from '@deriv-com/ui'; @@ -34,11 +36,19 @@ jest.mock('@deriv/api-v2', () => ({ useIsEuRegion: jest.fn(() => ({ data: false, })), + useIsHubRedirectionEnabled: jest.fn(() => ({ + isHubRedirectionEnabled: false, + })), useLandingCompany: jest.fn(() => ({ data: { financial_company: { shortcode: 'svg' }, }, })), + useSettings: jest.fn(() => ({ + data: { + trading_hub: 0, + }, + })), useWalletAccountsList: jest.fn(), })); @@ -123,6 +133,14 @@ describe('WalletsAddMoreCardBanner', () => { (useSyncLocalStorageClientAccounts as jest.Mock).mockReturnValue({ addWalletAccountToLocalStorage: mockAddWalletAccountToLocalStorage, }); + (useIsHubRedirectionEnabled as jest.Mock).mockReturnValue({ + isHubRedirectionEnabled: false, + }); + (useSettings as jest.Mock).mockReturnValue({ + data: { + trading_hub: 0, + }, + }); (useWalletAccountSwitcher as jest.Mock).mockReturnValue(mockSwitchWalletAccount); (useHistory as jest.Mock).mockReturnValue({ push: mockHistoryPush }); $root = document.createElement('div'); diff --git a/packages/wallets/src/components/WalletsChangeMT5Password/__tests/WalletSuccessChangeMT5Password.spec.tsx b/packages/wallets/src/components/WalletsChangeMT5Password/__tests/WalletSuccessChangeMT5Password.spec.tsx index f21d9ff31584..f16d6b86ad68 100644 --- a/packages/wallets/src/components/WalletsChangeMT5Password/__tests/WalletSuccessChangeMT5Password.spec.tsx +++ b/packages/wallets/src/components/WalletsChangeMT5Password/__tests/WalletSuccessChangeMT5Password.spec.tsx @@ -4,6 +4,8 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ModalProvider } from '../../ModalProvider'; import WalletSuccessChangeMT5Password from '../WalletSuccessChangeMT5Password'; +import { APIProvider } from '@deriv/api-v2'; +import WalletsAuthProvider from '../../../AuthProvider'; jest.mock('@deriv-com/ui', () => ({ ...jest.requireActual('@deriv-com/ui'), @@ -13,7 +15,13 @@ jest.mock('@deriv-com/ui', () => ({ describe('', () => { const mockOnClick = jest.fn(); - const wrapper = ({ children }: PropsWithChildren) => {children}; + const wrapper = ({ children }: PropsWithChildren) => ( + + + {children} + + + ); beforeEach(() => { jest.clearAllMocks(); diff --git a/packages/wallets/src/features/cashier/modules/TransactionStatus/components/CryptoTransaction/__tests__/CryptoTransaction.spec.tsx b/packages/wallets/src/features/cashier/modules/TransactionStatus/components/CryptoTransaction/__tests__/CryptoTransaction.spec.tsx index c7dee653d16e..4b7d29ac34f6 100644 --- a/packages/wallets/src/features/cashier/modules/TransactionStatus/components/CryptoTransaction/__tests__/CryptoTransaction.spec.tsx +++ b/packages/wallets/src/features/cashier/modules/TransactionStatus/components/CryptoTransaction/__tests__/CryptoTransaction.spec.tsx @@ -21,6 +21,14 @@ jest.mock('@deriv/api-v2', () => ({ useCurrencyConfig: jest.fn(() => ({ getConfig: (currency: 'BTC' | 'USD') => mockCurrencyConfig[currency], })), + useIsHubRedirectionEnabled: jest.fn(() => ({ + isHubRedirectionEnabled: false, + })), + useSettings: jest.fn(() => ({ + data: { + trading_hub: 0, + }, + })), })); const mockModalHide = jest.fn(); diff --git a/packages/wallets/src/features/cashier/modules/Transactions/components/TransactionsPendingRow/__tests__/TransactionsPendingRow.spec.tsx b/packages/wallets/src/features/cashier/modules/Transactions/components/TransactionsPendingRow/__tests__/TransactionsPendingRow.spec.tsx index d66f87dd82a3..30cb3d92153f 100644 --- a/packages/wallets/src/features/cashier/modules/Transactions/components/TransactionsPendingRow/__tests__/TransactionsPendingRow.spec.tsx +++ b/packages/wallets/src/features/cashier/modules/Transactions/components/TransactionsPendingRow/__tests__/TransactionsPendingRow.spec.tsx @@ -26,6 +26,14 @@ jest.mock('@deriv/api-v2', () => ({ useCurrencyConfig: jest.fn(() => ({ getConfig: (currency: 'BTC' | 'USD') => mockCurrencyConfig[currency], })), + useIsHubRedirectionEnabled: jest.fn(() => ({ + isHubRedirectionEnabled: false, + })), + useSettings: jest.fn(() => ({ + data: { + trading_hub: 0, + }, + })), })); jest.mock('react-router-dom', () => ({ diff --git a/packages/wallets/src/features/cashier/modules/Transactions/components/TransactionsPendingRow/components/TransactionsPendingRowField/__tests__/TransactionsPendingRowField.spec.tsx b/packages/wallets/src/features/cashier/modules/Transactions/components/TransactionsPendingRow/components/TransactionsPendingRowField/__tests__/TransactionsPendingRowField.spec.tsx index f378f53fad55..971e80e42710 100644 --- a/packages/wallets/src/features/cashier/modules/Transactions/components/TransactionsPendingRow/components/TransactionsPendingRowField/__tests__/TransactionsPendingRowField.spec.tsx +++ b/packages/wallets/src/features/cashier/modules/Transactions/components/TransactionsPendingRow/components/TransactionsPendingRowField/__tests__/TransactionsPendingRowField.spec.tsx @@ -3,6 +3,8 @@ import { useDevice } from '@deriv-com/ui'; import { fireEvent, render, screen } from '@testing-library/react'; import { ModalProvider } from '../../../../../../../../../components/ModalProvider'; import TransactionsPendingRowField from '../TransactionsPendingRowField'; +import { APIProvider } from '@deriv/api-v2'; +import WalletsAuthProvider from '../../../../../../../../../AuthProvider'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), @@ -50,9 +52,13 @@ describe('TransactionsPendingRowField', () => { value: 'Test Value', }; render( - - - + + + + + + + ); expect(screen.getByText('Test Name')).toBeInTheDocument(); @@ -73,9 +79,13 @@ describe('TransactionsPendingRowField', () => { (useDevice as jest.Mock).mockReturnValue({ isMobile: true }); render( - - - , + + + + + + + , { container: $root } ); fireEvent.click(screen.getByText('Test Value')); @@ -96,9 +106,13 @@ describe('TransactionsPendingRowField', () => { (useDevice as jest.Mock).mockReturnValue({ isMobile: true }); render( - - - , + + + + + + + , { container: $root } ); fireEvent.click(screen.getByText('Test Value')); diff --git a/packages/wallets/src/features/cfd/flows/CTrader/AddedCTraderAccountsList/__tests__/AddedCTraderAccountsList.spec.tsx b/packages/wallets/src/features/cfd/flows/CTrader/AddedCTraderAccountsList/__tests__/AddedCTraderAccountsList.spec.tsx index 5c69df099574..83f951a81338 100644 --- a/packages/wallets/src/features/cfd/flows/CTrader/AddedCTraderAccountsList/__tests__/AddedCTraderAccountsList.spec.tsx +++ b/packages/wallets/src/features/cfd/flows/CTrader/AddedCTraderAccountsList/__tests__/AddedCTraderAccountsList.spec.tsx @@ -8,6 +8,14 @@ import AddedCTraderAccountsList from '../AddedCTraderAccountsList'; jest.mock('@deriv/api-v2', () => ({ useCtraderAccountsList: jest.fn(), + useIsHubRedirectionEnabled: jest.fn(() => ({ + isHubRedirectionEnabled: false, + })), + useSettings: jest.fn(() => ({ + data: { + trading_hub: 0, + }, + })), })); jest.mock('../../../../modals', () => ({ diff --git a/packages/wallets/src/features/cfd/flows/CTrader/AvailableCTraderAccountsList/__tests__/AvailableCtraderAccountsList.spec.tsx b/packages/wallets/src/features/cfd/flows/CTrader/AvailableCTraderAccountsList/__tests__/AvailableCtraderAccountsList.spec.tsx index dee41db58359..056733308493 100644 --- a/packages/wallets/src/features/cfd/flows/CTrader/AvailableCTraderAccountsList/__tests__/AvailableCtraderAccountsList.spec.tsx +++ b/packages/wallets/src/features/cfd/flows/CTrader/AvailableCTraderAccountsList/__tests__/AvailableCtraderAccountsList.spec.tsx @@ -1,7 +1,12 @@ import React from 'react'; import { createMemoryHistory } from 'history'; import { Router } from 'react-router-dom'; -import { useActiveWalletAccount, useCreateOtherCFDAccount } from '@deriv/api-v2'; +import { + useActiveWalletAccount, + useCreateOtherCFDAccount, + useIsHubRedirectionEnabled, + useSettings, +} from '@deriv/api-v2'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ModalProvider } from '../../../../../../components/ModalProvider'; @@ -44,6 +49,14 @@ describe('AvailableCTraderAccountsList', () => { mutate: jest.fn(), status: 'idle', }); + (useIsHubRedirectionEnabled as jest.Mock).mockReturnValue({ + isHubRedirectionEnabled: false, + }); + (useSettings as jest.Mock).mockReturnValue({ + data: { + trading_hub: 0, + }, + }); (useIsRtl as jest.Mock).mockReturnValue(false); }); diff --git a/packages/wallets/src/features/cfd/flows/MT5/AddedMT5AccountsList/__tests__/AddedMT5AccountsList.spec.tsx b/packages/wallets/src/features/cfd/flows/MT5/AddedMT5AccountsList/__tests__/AddedMT5AccountsList.spec.tsx index 31c72b47ef78..edf6d32bc055 100644 --- a/packages/wallets/src/features/cfd/flows/MT5/AddedMT5AccountsList/__tests__/AddedMT5AccountsList.spec.tsx +++ b/packages/wallets/src/features/cfd/flows/MT5/AddedMT5AccountsList/__tests__/AddedMT5AccountsList.spec.tsx @@ -5,6 +5,8 @@ import { ModalProvider } from '../../../../../../components/ModalProvider'; import { MT5_ACCOUNT_STATUS, PlatformDetails } from '../../../../constants'; import AddedMT5AccountsList from '../AddedMT5AccountsList'; import { useAddedMT5Account } from '../hooks'; +import { APIProvider } from '@deriv/api-v2'; +import WalletsAuthProvider from '../../../../../../AuthProvider'; // mock function to check if correct props are passed to the modal components const mockPropsFn = jest.fn(); @@ -92,7 +94,13 @@ const mockUseAddedMT5AccountData = { showMT5TradeModal: true, }; -const wrapper: React.FC = ({ children }) => {children}; +const wrapper: React.FC = ({ children }) => ( + + + {children} + + +); describe('AddedMT5AccountsList', () => { // const mockShow = jest.fn(); diff --git a/packages/wallets/src/features/cfd/flows/OtherCFDs/Dxtrade/AddedDxtradeAccountsList/__test__/AddedDxtradeAccountsList.spec.tsx b/packages/wallets/src/features/cfd/flows/OtherCFDs/Dxtrade/AddedDxtradeAccountsList/__test__/AddedDxtradeAccountsList.spec.tsx index 643342f8c573..b67e0599612e 100644 --- a/packages/wallets/src/features/cfd/flows/OtherCFDs/Dxtrade/AddedDxtradeAccountsList/__test__/AddedDxtradeAccountsList.spec.tsx +++ b/packages/wallets/src/features/cfd/flows/OtherCFDs/Dxtrade/AddedDxtradeAccountsList/__test__/AddedDxtradeAccountsList.spec.tsx @@ -8,6 +8,14 @@ import AddedDxtradeAccountsList from '../AddedDxtradeAccountsList'; jest.mock('@deriv/api-v2', () => ({ useDxtradeAccountsList: jest.fn(), + useIsHubRedirectionEnabled: jest.fn(() => ({ + isHubRedirectionEnabled: false, + })), + useSettings: jest.fn(() => ({ + data: { + trading_hub: 0, + }, + })), })); jest.mock('../../../../../modals/MT5TradeModal', () => ({ diff --git a/packages/wallets/src/features/cfd/modals/CTraderSuccessModal/__tests__/CtraderSuccessModal.spec.tsx b/packages/wallets/src/features/cfd/modals/CTraderSuccessModal/__tests__/CtraderSuccessModal.spec.tsx index f61d0c3f0e58..d592b92925e1 100644 --- a/packages/wallets/src/features/cfd/modals/CTraderSuccessModal/__tests__/CtraderSuccessModal.spec.tsx +++ b/packages/wallets/src/features/cfd/modals/CTraderSuccessModal/__tests__/CtraderSuccessModal.spec.tsx @@ -7,6 +7,14 @@ import CTraderSuccessModal from '../CTraderSuccessModal'; jest.mock('@deriv/api-v2', () => ({ useCtraderAccountsList: jest.fn(), + useIsHubRedirectionEnabled: jest.fn(() => ({ + isHubRedirectionEnabled: false, + })), + useSettings: jest.fn(() => ({ + data: { + trading_hub: 0, + }, + })), })); jest.mock('@deriv-com/ui', () => ({ diff --git a/packages/wallets/src/features/cfd/modals/DxtradeEnterPasswordModal/__tests__/DxtradeEnterPasswordModal.spec.tsx b/packages/wallets/src/features/cfd/modals/DxtradeEnterPasswordModal/__tests__/DxtradeEnterPasswordModal.spec.tsx index c96476c25873..29cc8142fec5 100644 --- a/packages/wallets/src/features/cfd/modals/DxtradeEnterPasswordModal/__tests__/DxtradeEnterPasswordModal.spec.tsx +++ b/packages/wallets/src/features/cfd/modals/DxtradeEnterPasswordModal/__tests__/DxtradeEnterPasswordModal.spec.tsx @@ -4,6 +4,8 @@ import { useActiveWalletAccount, useCreateOtherCFDAccount, useDxtradeAccountsList, + useIsHubRedirectionEnabled, + useSettings, } from '@deriv/api-v2'; import { useDevice } from '@deriv-com/ui'; import { render, screen, waitFor } from '@testing-library/react'; @@ -131,6 +133,14 @@ describe('DxtradeEnterPasswordModal', () => { isSuccess: true, sendEmail: jest.fn(), }); + (useIsHubRedirectionEnabled as jest.Mock).mockReturnValue({ + isHubRedirectionEnabled: false, + }); + (useSettings as jest.Mock).mockReturnValue({ + data: { + trading_hub: 0, + }, + }); }); afterEach(() => { diff --git a/packages/wallets/src/features/cfd/screens/TradingPlatformStatus/__tests__/TradingPlatformStatus.spec.tsx b/packages/wallets/src/features/cfd/screens/TradingPlatformStatus/__tests__/TradingPlatformStatus.spec.tsx index 9f97e6f9d174..f19d17b9745c 100644 --- a/packages/wallets/src/features/cfd/screens/TradingPlatformStatus/__tests__/TradingPlatformStatus.spec.tsx +++ b/packages/wallets/src/features/cfd/screens/TradingPlatformStatus/__tests__/TradingPlatformStatus.spec.tsx @@ -4,6 +4,8 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ModalProvider } from '../../../../../components/ModalProvider'; import TradingPlatformStatus from '../TradingPlatformStatus'; +import { APIProvider } from '@deriv/api-v2'; +import WalletsAuthProvider from '../../../../../AuthProvider'; jest.mock('@deriv-com/ui', () => ({ ...jest.requireActual('@deriv-com/ui'), @@ -26,9 +28,13 @@ describe('TradingPlatformStatus', () => { it('renders default content for maintenance status', () => { render( - - - + + + + + + + ); expect(screen.getByText('Server Maintenance')).toBeInTheDocument(); @@ -40,9 +46,13 @@ describe('TradingPlatformStatus', () => { it('renders default content for unavailable status', () => { render( - - - + + + + + + + ); expect(screen.getByText('Account Unavailable')).toBeInTheDocument(); @@ -55,9 +65,13 @@ describe('TradingPlatformStatus', () => { it('calls hide when clicking on OK button', async () => { (useDevice as jest.Mock).mockReturnValue({ isDesktop: false }); render( - - - + + + + + + + ); await userEvent.click(screen.getByRole('button', { name: 'OK' })); diff --git a/packages/wallets/src/routes/Router.tsx b/packages/wallets/src/routes/Router.tsx index 4613fc546469..b0ddffa5d871 100644 --- a/packages/wallets/src/routes/Router.tsx +++ b/packages/wallets/src/routes/Router.tsx @@ -26,6 +26,10 @@ type TWalletsRoute = export type TRoute = '/endpoint' | `?${string}` | `${TWalletsRoute}`; +type TRouterProps = { + isHubRedirectionEnabled: boolean; +}; + // wallets routes which have their states interface WalletsRouteState { '/': { accountsActiveTabIndex: number }; @@ -71,7 +75,7 @@ declare module 'react-router-dom' { export function useRouteMatch(path: TRoute): boolean; } -const Router: React.FC = () => { +const Router: React.FC = ({ isHubRedirectionEnabled }) => { return ( { path={'/'} render={() => ( }> - + )} /> diff --git a/packages/wallets/src/routes/WalletsListingRoute/WalletsListingRoute.tsx b/packages/wallets/src/routes/WalletsListingRoute/WalletsListingRoute.tsx index 3db9f2f2dc34..ad6b483bcf67 100644 --- a/packages/wallets/src/routes/WalletsListingRoute/WalletsListingRoute.tsx +++ b/packages/wallets/src/routes/WalletsListingRoute/WalletsListingRoute.tsx @@ -11,10 +11,14 @@ import { import ResetMT5PasswordHandler from '../../features/cfd/ResetMT5PasswordHandler'; import './WalletsListingRoute.scss'; +type TWalletsListingRouteProps = { + isHubRedirectionEnabled: boolean; +}; + const LazyWalletsCarousel = lazy(() => import('../../components/WalletsCarousel/WalletsCarousel')); const LazyDesktopWalletsList = lazy(() => import('../../components/DesktopWalletsList/DesktopWalletsList')); -const WalletsListingRoute: React.FC = () => { +const WalletsListingRoute: React.FC = ({ isHubRedirectionEnabled }) => { const { isDesktop } = useDevice(); const { data: isEuRegion, isLoading: isEuRegionLoading } = useIsEuRegion(); const { data: activeWallet } = useActiveWalletAccount(); @@ -22,6 +26,10 @@ const WalletsListingRoute: React.FC = () => { const hasAddedWallet = allWallets?.some(wallet => wallet.is_added); const shouldHideAddMoreCarousel = isAllWalletsLoading || isEuRegionLoading || (isEuRegion && hasAddedWallet); + if (isHubRedirectionEnabled) { + return null; + } + return (
{isDesktop && } diff --git a/packages/wallets/src/routes/WalletsListingRoute/__tests__/WalletsListingRoute.spec.tsx b/packages/wallets/src/routes/WalletsListingRoute/__tests__/WalletsListingRoute.spec.tsx index e7736d69682d..3693f93b390b 100644 --- a/packages/wallets/src/routes/WalletsListingRoute/__tests__/WalletsListingRoute.spec.tsx +++ b/packages/wallets/src/routes/WalletsListingRoute/__tests__/WalletsListingRoute.spec.tsx @@ -60,7 +60,7 @@ describe('WalletsListingRoute', () => { }); it('renders DesktopWalletsList and WalletsAddMoreCarousel correctly on desktop', async () => { - render(, { wrapper }); + render(, { wrapper }); expect(screen.getByText('WalletListHeader')).toBeInTheDocument(); expect(screen.queryByText('WalletsCarousel')).not.toBeInTheDocument(); expect(await screen.findByText('DesktopWalletsList')).toBeInTheDocument(); @@ -69,7 +69,7 @@ describe('WalletsListingRoute', () => { it('renders WalletsCarousel and WalletsAddMoreCarousel correctly on mobile', async () => { (useDevice as jest.Mock).mockReturnValue({ isMobile: true }); - render(, { wrapper }); + render(, { wrapper }); expect(screen.queryByText('WalletListHeader')).not.toBeInTheDocument(); expect(screen.queryByText('DesktopWalletsList')).not.toBeInTheDocument(); expect(await screen.findByText('WalletsCarousel')).toBeInTheDocument(); @@ -79,14 +79,14 @@ describe('WalletsListingRoute', () => { (useWalletAccountsList as jest.Mock).mockReturnValue({ data: [{ is_added: true }], }); - render(, { wrapper }); + render(, { wrapper }); expect(screen.queryByText('WalletsAddMoreCarousel')).not.toBeInTheDocument(); }); it('displays the wallet disclaimer banner if the user is in the EU region and has a non-virtual wallet', () => { (useDevice as jest.Mock).mockReturnValue({ isDesktop: true, isMobile: false }); (useIsEuRegion as jest.Mock).mockReturnValue({ data: true }); - render(, { wrapper }); + render(, { wrapper }); expect(screen.getByText('WalletsDisclaimerBanner')).toBeInTheDocument(); }); @@ -94,7 +94,7 @@ describe('WalletsListingRoute', () => { (useDevice as jest.Mock).mockReturnValue({ isDesktop: true, isMobile: false }); (useActiveWalletAccount as jest.Mock).mockReturnValue({ data: { is_virtual: true } }); (useIsEuRegion as jest.Mock).mockReturnValue({ data: true }); - render(, { wrapper }); + render(, { wrapper }); expect(screen.queryByText('WalletsDisclaimerBanner')).not.toBeInTheDocument(); }); });