Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TRAH] Sergei / TRAH - 3679 / Add a full screen modal after Sign up - to allow users to go to demo or proceed with real account creation #15758

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import AfterSignupFlow from '../after-signup-flow';
import { render } from '@testing-library/react';
import { StoreProvider, mockStore } from '@deriv/stores';
import { useContentFlag, useGrowthbookGetFeatureValue } from '@deriv/hooks';

jest.mock('@deriv/hooks', () => ({
...jest.requireActual('@deriv/hooks'),
useContentFlag: jest.fn(() => ({ is_cr_demo: true, is_eu_demo: false })),
useGrowthbookGetFeatureValue: jest.fn(() => [false, true]),
}));

describe('AfterSignupFlow', () => {
const mockedOpenRealAccountSignup = jest.fn();
const mockedSetIsFromSignupAccount = jest.fn();
const mockedSetIsSetupRealAccountOrGoToDemoModalVisible = jest.fn();

const mockDefault = mockStore({
client: {
is_logged_in: true,
has_active_real_account: false,
},
ui: {
is_from_signup_account: true,
openRealAccountSignup: mockedOpenRealAccountSignup,
setIsFromSignupAccount: mockedSetIsFromSignupAccount,
},
traders_hub: {
setIsSetupRealAccountOrGoToDemoModalVisible: mockedSetIsSetupRealAccountOrGoToDemoModalVisible,
},
});

const wrapper = (mock: ReturnType<typeof mockStore> = mockDefault) => {
const Component = ({ children }: { children: JSX.Element }) => (
<StoreProvider store={mock}>{children}</StoreProvider>
);
return Component;
};

afterEach(() => {
jest.clearAllMocks();
});

it('check if growthbook feature flags are false', () => {
(useGrowthbookGetFeatureValue as jest.Mock).mockReturnValue([false, true]);

render(<AfterSignupFlow />, {
wrapper: wrapper(),
});

expect(mockedOpenRealAccountSignup).not.toBeCalled();
expect(mockedSetIsFromSignupAccount).not.toBeCalled();
expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).not.toBeCalled();
});

it('check if growthbook feature flags "direct-real-account-creation-flow" is true for is_cr_demo = true', () => {
(useGrowthbookGetFeatureValue as jest.Mock).mockReturnValueOnce([true, true]);
(useContentFlag as jest.Mock).mockReturnValue({ is_cr_demo: true, is_eu_demo: false });

render(<AfterSignupFlow />, {
wrapper: wrapper(),
});

expect(mockedOpenRealAccountSignup).toBeCalled();
expect(mockedSetIsFromSignupAccount).toBeCalled();
expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).not.toBeCalled();
});

it('check if growthbook feature flags "direct-real-account-creation-flow" is true for is_eu_demo = true', () => {
(useGrowthbookGetFeatureValue as jest.Mock).mockReturnValueOnce([true, true]);
(useContentFlag as jest.Mock).mockReturnValue({ is_cr_demo: false, is_eu_demo: true });

render(<AfterSignupFlow />, {
wrapper: wrapper(),
});

expect(mockedOpenRealAccountSignup).toBeCalled();
expect(mockedSetIsFromSignupAccount).toBeCalled();
expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).not.toBeCalled();
});

it('check if growthbook feature flags "show_setup_real_or_go_demo" is true', () => {
(useGrowthbookGetFeatureValue as jest.Mock).mockReturnValueOnce([false, true]);
(useGrowthbookGetFeatureValue as jest.Mock).mockReturnValueOnce([true, true]);

render(<AfterSignupFlow />, {
wrapper: wrapper(),
});

expect(mockedOpenRealAccountSignup).not.toBeCalled();
expect(mockedSetIsFromSignupAccount).toBeCalled();
expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).toBeCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { useEffect } from 'react';
import { useContentFlag, useGrowthbookGetFeatureValue } from '@deriv/hooks';
import { observer, useStore } from '@deriv/stores';
import { Jurisdiction } from '@deriv/shared';

const AfterSignupFlow = observer(() => {
const { client, ui, traders_hub } = useStore();
const { openRealAccountSignup, is_from_signup_account, setIsFromSignupAccount } = ui;
const { is_logged_in, has_active_real_account } = client;
const { setIsSetupRealAccountOrGoToDemoModalVisible } = traders_hub;

const { is_cr_demo, is_eu_demo } = useContentFlag();

const [direct_to_real_account_creation] = useGrowthbookGetFeatureValue({
featureFlag: 'direct-real-account-creation-flow',
defaultValue: false,
});

const [show_setup_real_or_go_demo] = useGrowthbookGetFeatureValue({
featureFlag: 'show_setup_real_or_go_demo',
defaultValue: false,
});

useEffect(() => {
if (!has_active_real_account && is_from_signup_account && is_logged_in) {
// move the user directly to setup real account
if (direct_to_real_account_creation && !show_setup_real_or_go_demo) {
sergei-deriv marked this conversation as resolved.
Show resolved Hide resolved
if (is_cr_demo) {
openRealAccountSignup(Jurisdiction.SVG);
setIsFromSignupAccount(false);
} else if (is_eu_demo) {
openRealAccountSignup(Jurisdiction.MALTA_INVEST);
setIsFromSignupAccount(false);
}
}

// show setup real or go to demo modal for user
if (!direct_to_real_account_creation && show_setup_real_or_go_demo) {
setIsSetupRealAccountOrGoToDemoModalVisible(true);
setIsFromSignupAccount(false);
}
}
}, [
is_cr_demo,
is_eu_demo,
has_active_real_account,
is_from_signup_account,
is_logged_in,
direct_to_real_account_creation,
openRealAccountSignup,
setIsFromSignupAccount,
]);

return null;
});

export default AfterSignupFlow;
3 changes: 3 additions & 0 deletions packages/appstore/src/components/after-signup-flow/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import AfterSignupFlow from './after-signup-flow';

export default AfterSignupFlow;
2 changes: 2 additions & 0 deletions packages/appstore/src/components/app.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@700&display=swap');
sergei-deriv marked this conversation as resolved.
Show resolved Hide resolved

.dashboard {
@include desktop-screen {
height: calc(100vh - #{$HEADER_HEIGHT} - #{$FOOTER_HEIGHT});
Expand Down
13 changes: 13 additions & 0 deletions packages/appstore/src/components/modals/modal-manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,17 @@ const CTraderTransferModal = makeLazyLoader(
() => <Loading />
)();

const SetupRealAccountOrGoToDemoModal = makeLazyLoader(
() =>
moduleLoader(
() =>
import(
/* webpackChunkName: "modal_setup-real-account-or-go-to-demo" */ './setup-real-account-or-go-to-demo-modal'
)
),
() => <Loading />
)();

type TCurrentList = DetailsOfEachMT5Loginid & {
enabled: number;
};
Expand Down Expand Up @@ -225,6 +236,7 @@ const ModalManager = () => {
is_failed_verification_modal_visible,
is_regulators_compare_modal_visible,
is_wallet_migration_failed,
is_setup_real_account_or_go_to_demo_modal_visible,
} = traders_hub;

const [password_manager, setPasswordManager] = React.useState<{
Expand Down Expand Up @@ -350,6 +362,7 @@ const ModalManager = () => {
{is_eligible && <WalletsUpgradeModal />}
</React.Fragment>
)}
{is_setup_real_account_or_go_to_demo_modal_visible && <SetupRealAccountOrGoToDemoModal />}
</React.Fragment>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React from 'react';
import { SetupRealAccountOrGoToDemoModalContent } from '../setup-real-account-or-go-to-demo-modal-content';
import { render, screen } from '@testing-library/react';
import { Analytics } from '@deriv-com/analytics';
import { useContentFlag } from '@deriv/hooks';
import { StoreProvider, mockStore } from '@deriv/stores';
import userEvent from '@testing-library/user-event';
import { Jurisdiction } from '@deriv/shared';

jest.mock('@deriv/hooks', () => ({
...jest.requireActual('@deriv/hooks'),
useContentFlag: jest.fn(() => ({ is_cr_demo: true, is_eu_demo: false })),
}));

jest.mock('@deriv-com/analytics', () => ({
...jest.requireActual('@deriv-com/analytics'),
Analytics: {
trackEvent: jest.fn(),
},
}));

describe('SetupRealAccountOrGoToDemoModalContent', () => {
const mockedOpenRealAccountSignup = jest.fn();
const mockedSetIsFromSignupAccount = jest.fn();
const mockedSetIsSetupRealAccountOrGoToDemoModalVisible = jest.fn();
const mockTrack = Analytics.trackEvent;

const mockDefault = mockStore({
ui: {
is_from_signup_account: true,
openRealAccountSignup: mockedOpenRealAccountSignup,
setIsFromSignupAccount: mockedSetIsFromSignupAccount,
},
traders_hub: {
is_setup_real_account_or_go_to_demo_modal_visible: true,
setIsSetupRealAccountOrGoToDemoModalVisible: mockedSetIsSetupRealAccountOrGoToDemoModalVisible,
},
});

const wrapper = (mock: ReturnType<typeof mockStore> = mockDefault) => {
const Component = ({ children }: { children: JSX.Element }) => (
<StoreProvider store={mock}>{children}</StoreProvider>
);
return Component;
};

beforeEach(() => {
jest.clearAllMocks();
});

it('Should render correctly in desktop', () => {
const { container } = render(<SetupRealAccountOrGoToDemoModalContent />, {
wrapper: wrapper(),
});

const title = screen.getByText(/start your trading journey/i);

expect(container).toBeInTheDocument();
expect(title).toBeInTheDocument();
});

it('Should render correctly in responsive', () => {
const { container } = render(<SetupRealAccountOrGoToDemoModalContent is_responsive />, {
wrapper: wrapper(),
});

const title = screen.getByText(/start your trading journey/i);

expect(container).toBeInTheDocument();
expect(title).toBeInTheDocument();
});

it('User click "setup real account" button when is_cr_demo = true', () => {
(useContentFlag as jest.Mock).mockReturnValue({ is_cr_demo: true, is_eu_demo: false });

const { container } = render(<SetupRealAccountOrGoToDemoModalContent />, {
wrapper: wrapper(),
});

const setup_btn = screen.getByRole('button', {
name: /set up your real account/i,
});

expect(container).toBeInTheDocument();

userEvent.click(setup_btn);

expect(mockTrack).toBeCalledTimes(1);

expect(mockedOpenRealAccountSignup).toBeCalledTimes(1);
expect(mockedOpenRealAccountSignup).toBeCalledWith(Jurisdiction.SVG);

expect(mockedSetIsFromSignupAccount).toBeCalledTimes(1);
expect(mockedSetIsFromSignupAccount).toBeCalledWith(false);

expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).toBeCalledTimes(1);
expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).toBeCalledWith(false);
});

it('User click "setup real account" button when is_eu_demo = true', () => {
(useContentFlag as jest.Mock).mockReturnValue({ is_cr_demo: false, is_eu_demo: true });

const { container } = render(<SetupRealAccountOrGoToDemoModalContent />, {
wrapper: wrapper(),
});

const setup_btn = screen.getByRole('button', {
name: /set up your real account/i,
});

expect(container).toBeInTheDocument();

userEvent.click(setup_btn);

expect(mockTrack).toBeCalledTimes(1);

expect(mockedOpenRealAccountSignup).toBeCalledTimes(1);
expect(mockedOpenRealAccountSignup).toBeCalledWith(Jurisdiction.MALTA_INVEST);

expect(mockedSetIsFromSignupAccount).toBeCalledTimes(1);
expect(mockedSetIsFromSignupAccount).toBeCalledWith(false);

expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).toBeCalledTimes(1);
expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).toBeCalledWith(false);
});

it('User click "take me to demo" button', () => {
const { container } = render(<SetupRealAccountOrGoToDemoModalContent />, {
wrapper: wrapper(),
});

const demo_btn = screen.getByRole('button', {
name: /take me to demo/i,
});

expect(container).toBeInTheDocument();

userEvent.click(demo_btn);

expect(mockTrack).toBeCalledTimes(1);

expect(mockedSetIsFromSignupAccount).toBeCalledTimes(1);
expect(mockedSetIsFromSignupAccount).toBeCalledWith(false);

expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).toBeCalledTimes(1);
expect(mockedSetIsSetupRealAccountOrGoToDemoModalVisible).toBeCalledWith(false);
});
});
Loading
Loading