Skip to content

Commit

Permalink
[WALL] george / WALL-5234 / Wallets force migration integration with …
Browse files Browse the repository at this point in the history
…GrowthBook (#17819)

* feat(wallets): ✨ implement force migration on feature flag

* refactor: streamline client data retrieval and enhance analytics logging (#44)

* refactor: update getAccountInfo to handle residence country retrieval and enhance analytics logging
  • Loading branch information
heorhi-deriv authored Dec 30, 2024
1 parent 611f623 commit 8863579
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from 'react';

import { useGrowthbookGetFeatureValue, useWalletMigration } from '@deriv/hooks';
import { mockStore, StoreProvider } from '@deriv/stores';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { useWalletMigration } from '@deriv/hooks';
import { StoreProvider, mockStore } from '@deriv/stores';

import WalletsUpgradeModal from '../wallets-upgrade-modal';

const mockStartMigration = jest.fn();
Expand All @@ -11,8 +13,11 @@ jest.mock('@deriv/hooks', () => ({
...jest.requireActual('@deriv/hooks'),
useWalletMigration: jest.fn(() => ({
is_eligible: true,
is_in_progress: false,
is_migrating: false,
startMigration: mockStartMigration,
})),
useGrowthbookGetFeatureValue: jest.fn(() => [false]),
}));

jest.mock('@deriv/stores', () => ({
Expand All @@ -33,7 +38,7 @@ describe('<WalletsUpgradeModal />', () => {
document.body.removeChild(modal_root_el);
});

it('Should show modal if user is eligible for migration and is_wallet_modal_closed is not in sessionStorage', () => {
it('shows modal if user is eligible for migration and is_wallet_modal_closed is not in sessionStorage', () => {
const mock = mockStore({
traders_hub: {
toggleWalletsUpgrade: jest.fn(),
Expand All @@ -52,11 +57,39 @@ describe('<WalletsUpgradeModal />', () => {

render(<WalletsUpgradeModal />, { wrapper });

const close_button = screen.getByTestId('dt_modal_close_icon');

expect(screen.getByText('Introducing Wallets')).toBeInTheDocument();
expect(screen.getByText('Enable now')).toBeInTheDocument();
expect(close_button).toBeInTheDocument();
});

it('shows modal without close button for force migration if force migration is enabled and user is not migrating or in progress', () => {
(useGrowthbookGetFeatureValue as jest.Mock).mockReturnValueOnce([true]);
const mock = mockStore({
traders_hub: {
toggleWalletsUpgrade: jest.fn(),
},
ui: {
is_mobile: false,
is_desktop: true,
},
});

const wrapper = ({ children }: { children: JSX.Element }) => (
<StoreProvider store={mock}>{children}</StoreProvider>
);

render(<WalletsUpgradeModal />, { wrapper });

const close_button = screen.queryByTestId('dt_modal_close_icon');

expect(screen.getByText('Introducing Wallets')).toBeInTheDocument();
expect(screen.getByText('Enable now')).toBeInTheDocument();
expect(close_button).not.toBeInTheDocument();
});

it('Should not show modal if user is not eligible for migration', () => {
it('does not show modal if user is not eligible for migration', () => {
const mock = mockStore({
traders_hub: {
toggleWalletsUpgrade: jest.fn(),
Expand All @@ -82,7 +115,7 @@ describe('<WalletsUpgradeModal />', () => {
expect(screen.queryByText('Enable now')).not.toBeInTheDocument();
});

it('Should not show modal if is_wallet_modal_closed is in sessionStorage', () => {
it('does not show modal if is_wallet_modal_closed is in sessionStorage', () => {
const mock = mockStore({
traders_hub: {
toggleWalletsUpgrade: jest.fn(),
Expand All @@ -107,7 +140,7 @@ describe('<WalletsUpgradeModal />', () => {
expect(screen.queryByText('Enable now')).not.toBeInTheDocument();
});

it('Should close modal when close button is clicked', () => {
it('closes modal when close button is clicked', async () => {
const mock = mockStore({
traders_hub: {
toggleWalletsUpgrade: jest.fn(),
Expand All @@ -128,13 +161,13 @@ describe('<WalletsUpgradeModal />', () => {
render(<WalletsUpgradeModal />, { wrapper });

const close_button = screen.getByTestId('dt_modal_close_icon');
userEvent.click(close_button);
await userEvent.click(close_button);

expect(setModalOpen).toHaveBeenCalledWith(false);
expect(sessionStorage.getItem('is_wallet_migration_modal_closed')).toBe('true');
});

it('Should start migration when Enable now button is clicked', () => {
it('starts migration when Enable now button is clicked', async () => {
const mock = mockStore({
traders_hub: {
toggleWalletsUpgrade: jest.fn(),
Expand All @@ -154,7 +187,7 @@ describe('<WalletsUpgradeModal />', () => {
render(<WalletsUpgradeModal />, { wrapper });

const enable_now_button = screen.getByRole('button', { name: 'Enable now' });
userEvent.click(enable_now_button);
await userEvent.click(enable_now_button);

expect(mockStartMigration).toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import React from 'react';
import { Analytics, TEvents } from '@deriv-com/analytics';
import classNames from 'classnames';
import { Button, Text, Modal, VideoPlayer } from '@deriv/components';
import { localize, Localize } from '@deriv/translations';

import { Button, Modal, Text, VideoPlayer } from '@deriv/components';
import { useGrowthbookGetFeatureValue, useWalletMigration } from '@deriv/hooks';
import { observer, useStore } from '@deriv/stores';
import { useWalletMigration } from '@deriv/hooks';
import { Localize, localize } from '@deriv/translations';
import { Analytics, TEvents } from '@deriv-com/analytics';
import { SectionMessage } from '@deriv-com/ui';

import {
getWalletMigrationVideoTranslations,
WALLET_MIGRATION_VIDEO_TRANSLATIONS,
} from 'Constants/wallet-migration-video-translations';

import './wallets-upgrade-modal.scss';

const trackAnalyticsEvent = (
Expand All @@ -30,21 +33,27 @@ const WalletsUpgradeModal = observer(() => {
const { current_language } = common;
const { is_demo, is_real_wallets_upgrade_on, toggleWalletsUpgrade } = traders_hub;
const { is_desktop, is_mobile } = ui;
const { is_eligible, startMigration } = useWalletMigration();
const { is_eligible, is_migrating, is_in_progress, startMigration } = useWalletMigration();
const [is_wallet_force_migration_enabled] = useGrowthbookGetFeatureValue({
featureFlag: 'wallet_force_migration',
defaultValue: false,
});
const account_mode = is_demo ? 'demo' : 'real';
const isWalletMigrationModalClosed = localStorage.getItem('is_wallet_migration_modal_closed');
const [modalOpen, setModalOpen] = React.useState(!isWalletMigrationModalClosed);
const is_open = (is_eligible && modalOpen) || is_real_wallets_upgrade_on;
const is_modal_open_for_force_migration = is_wallet_force_migration_enabled && !(is_in_progress || is_migrating);
const is_modal_open_for_non_force_migration = (is_eligible && modalOpen) || is_real_wallets_upgrade_on;
const is_modal_open = is_modal_open_for_force_migration || is_modal_open_for_non_force_migration;

const video_src = getWalletMigrationVideoTranslations(
current_language as keyof typeof WALLET_MIGRATION_VIDEO_TRANSLATIONS
);

React.useEffect(() => {
if (is_open) {
if (is_modal_open) {
trackAnalyticsEvent('open', account_mode);
}
}, [account_mode, is_open]);
}, [account_mode, is_modal_open]);

const closeModal = () => {
setModalOpen(false);
Expand All @@ -66,7 +75,8 @@ const WalletsUpgradeModal = observer(() => {
return (
<Modal
className='wallets-upgrade-modal'
is_open={is_open}
has_close_icon={!is_wallet_force_migration_enabled}
is_open={is_modal_open}
width={is_desktop ? '77.6rem' : '32.8rem'}
title=' '
toggleModal={onToggleModalHandler}
Expand Down
33 changes: 22 additions & 11 deletions packages/core/src/Stores/client-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -1123,16 +1123,11 @@ export default class ClientStore extends BaseStore {
: window.location.hostname;

// eslint-disable-next-line max-len
const {
loginid,
email,
landing_company_shortcode,
currency,
residence,
account_settings,
preferred_language,
user_id,
} = this;
const { loginid, landing_company_shortcode, currency, account_settings, preferred_language, user_id } = this;

const client_accounts = JSON.parse(LocalStore.get(storage_key));
const email = this.email || client_accounts[loginid]?.email;
const residence = this.residence || client_accounts[loginid]?.residence;

const { first_name, last_name, name } = account_settings;
if (loginid && email) {
Expand Down Expand Up @@ -1815,9 +1810,25 @@ export default class ClientStore extends BaseStore {
?.match(/[a-zA-Z]+/g)
?.join('');
setTimeout(async () => {
let residence_country = '';
if (this.residence) {
residence_country = this.residence;
} else {
try {
const { country_code } = (await WS.authorized.cache.getSettings())?.get_settings || {
country_code: '',
};
residence_country = country_code;
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error getting residence country', error);
}
}

const analytics_config = {
loggedIn: this.is_logged_in,
account_type: broker === 'null' ? 'unlogged' : broker,
residence_country: this.residence,
residence_country,
app_id: String(getAppId()),
device_type: isMobile() ? 'mobile' : 'desktop',
language: getLanguage(),
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/Utils/Analytics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ export const AnalyticsInitializer = async () => {
}
: Cookies.getJSON('utm_data');

const client_information = Cookies.getJSON('client_information');

const config = {
growthbookKey: flags.marketing_growthbook ? process.env.GROWTHBOOK_CLIENT_KEY : undefined,
growthbookDecryptionKey: flags.marketing_growthbook ? process.env.GROWTHBOOK_DECRYPTION_KEY : undefined,
rudderstackKey: process.env.RUDDERSTACK_KEY,
growthbookOptions: {
attributes: {
loggedIn: !!Cookies.get('clients_information'),
loggedIn: !!client_information,
account_type: account_type === 'null' ? 'unlogged' : account_type,
app_id: String(getAppId()),
device_type: window.innerWidth <= MAX_MOBILE_WIDTH ? 'mobile' : 'desktop',
Expand All @@ -49,6 +51,7 @@ export const AnalyticsInitializer = async () => {
network_type: navigator.connection?.effectiveType,
network_rtt: navigator.connection?.rtt,
network_downlink: navigator.connection?.downlink,
residence_country: client_information?.residence,
},
},
};
Expand Down

0 comments on commit 8863579

Please sign in to comment.