diff --git a/packages/reports/src/Components/Elements/Modals/AccountVerificationPendingModal/__tests__/account-verification-pending-modal.spec.tsx b/packages/reports/src/Components/Elements/Modals/AccountVerificationPendingModal/__tests__/account-verification-pending-modal.spec.tsx new file mode 100644 index 000000000000..6b0cf144d549 --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/AccountVerificationPendingModal/__tests__/account-verification-pending-modal.spec.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import AccountVerificationPendingModal from '../account-verification-pending-modal'; + +describe('', () => { + let modal_root_el: HTMLDivElement; + + beforeAll(() => { + modal_root_el = document.createElement('div'); + modal_root_el.setAttribute('id', 'modal_root'); + document.body.appendChild(modal_root_el); + }); + + afterAll(() => { + document.body.removeChild(modal_root_el); + }); + + const mock_props: React.ComponentProps = { + is_visible: true, + onConfirm: jest.fn(), + }; + + const modal_heading = /Pending verification/; + const modal_desc = + /You cannot trade as your documents are still under review. We will notify you by email once your verification is approved./i; + + it('should render the component AccountVerificationPendingModal if is_visible is true', () => { + render(); + + expect(screen.getByRole('heading', { name: modal_heading })).toBeInTheDocument(); + expect(screen.getByText(modal_desc)).toBeInTheDocument(); + + const confirm_ok_btn = screen.getByRole('button', { name: /OK/i }); + expect(confirm_ok_btn).toBeInTheDocument(); + expect(confirm_ok_btn).toBeEnabled(); + }); + + it('should call onConfirm when clicking on OK button', () => { + render(); + + const confirm_ok_btn = screen.getByRole('button', { name: /OK/i }); + userEvent.click(confirm_ok_btn); + expect(mock_props.onConfirm).toBeCalledTimes(1); + }); + + it('should not render the component if is_visible is false ', () => { + render(); + + expect(screen.queryByRole('heading', { name: modal_heading })).not.toBeInTheDocument(); + expect(screen.queryByText(modal_desc)).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: /OK/i })).not.toBeInTheDocument(); + }); +}); diff --git a/packages/reports/src/Components/Elements/Modals/AccountVerificationPendingModal/account-verification-pending-modal.tsx b/packages/reports/src/Components/Elements/Modals/AccountVerificationPendingModal/account-verification-pending-modal.tsx new file mode 100644 index 000000000000..d0df8a11878e --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/AccountVerificationPendingModal/account-verification-pending-modal.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Button, Modal } from '@deriv/components'; +import { Localize } from '@deriv/translations'; + +type TAccountVerificationPendingModalProps = { + is_visible: boolean; + onConfirm: () => void; +}; + +const AccountVerificationPendingModal = ({ is_visible, onConfirm }: TAccountVerificationPendingModalProps) => ( + } + toggleModal={onConfirm} + className='account-verification-pending-modal' + > + + + + + + + +); + +export default AccountVerificationPendingModal; diff --git a/packages/reports/src/Components/Elements/Modals/AccountVerificationPendingModal/index.ts b/packages/reports/src/Components/Elements/Modals/AccountVerificationPendingModal/index.ts new file mode 100644 index 000000000000..1f0c69529153 --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/AccountVerificationPendingModal/index.ts @@ -0,0 +1,3 @@ +import AccountVerificationPendingModal from './account-verification-pending-modal'; + +export default AccountVerificationPendingModal; diff --git a/packages/reports/src/Components/Elements/Modals/MarketUnavailableModal/__tests__/market-unavailable.spec.tsx b/packages/reports/src/Components/Elements/Modals/MarketUnavailableModal/__tests__/market-unavailable.spec.tsx new file mode 100644 index 000000000000..be3f73570db3 --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/MarketUnavailableModal/__tests__/market-unavailable.spec.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import { render, screen } from '@testing-library/react'; +import MarketUnavailableModal from '../market-unavailable'; +import { mockStore } from '@deriv/stores'; +import ReportsProviders from '../../../../../reports-providers'; + +const mock_props = { + onCancel: jest.fn(), + onConfirm: jest.fn(), +}; + +describe('MarketUnavailableModal', () => { + it('should render modal component', () => { + const mock_root_store = mockStore({ ui: { has_only_forward_starting_contracts: true } }); + + (ReactDOM.createPortal as jest.Mock) = jest.fn(component => { + return component; + }); + + render(, { + wrapper: ({ children }) => {children}, + }); + + expect(screen.getByText(/This market is not yet/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/reports/src/Components/Elements/Modals/MarketUnavailableModal/index.ts b/packages/reports/src/Components/Elements/Modals/MarketUnavailableModal/index.ts new file mode 100644 index 000000000000..62c77323d14e --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/MarketUnavailableModal/index.ts @@ -0,0 +1,3 @@ +import MarketUnavailableModal from './market-unavailable'; + +export default MarketUnavailableModal; diff --git a/packages/reports/src/Components/Elements/Modals/MarketUnavailableModal/market-unavailable.tsx b/packages/reports/src/Components/Elements/Modals/MarketUnavailableModal/market-unavailable.tsx new file mode 100644 index 000000000000..2d1154801113 --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/MarketUnavailableModal/market-unavailable.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import { Dialog } from '@deriv/components'; +import { getPlatformSettings } from '@deriv/shared'; +import { localize, Localize } from '@deriv/translations'; +import { observer, useStore } from '@deriv/stores'; + +type TMarketUnavailableModalProps = { + is_loading?: boolean; + onCancel: () => void; + onConfirm: () => void; +}; + +const MarketUnavailableModal = observer(({ is_loading, onCancel, onConfirm }: TMarketUnavailableModalProps) => { + const { ui } = useStore(); + const { disableApp, enableApp, has_only_forward_starting_contracts: is_visible } = ui; + + return ( + } + confirm_button_text={localize('Stay on {{platform_name_trader}}', { + platform_name_trader: getPlatformSettings('trader').name, + })} + cancel_button_text={localize('Go to {{platform_name_smarttrader}}', { + platform_name_smarttrader: getPlatformSettings('smarttrader').name, + })} + onConfirm={onConfirm} + onCancel={onCancel} + is_mobile_full_width={false} + is_visible={is_visible} + disableApp={disableApp} + enableApp={enableApp} + is_loading={is_loading} + > + + + ); +}); + +export default MarketUnavailableModal; diff --git a/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/account-verification-required-modal.spec.tsx b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/account-verification-required-modal.spec.tsx new file mode 100644 index 000000000000..5b078a65f760 --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/account-verification-required-modal.spec.tsx @@ -0,0 +1,108 @@ +import React from 'react'; +import { createBrowserHistory } from 'history'; +import { Router } from 'react-router-dom'; +import { screen, render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { routes } from '@deriv/shared'; +import { useStore } from '@deriv/stores'; +import AccountVerificationRequiredModal from '../account-verification-required-modal'; + +type TModal = React.FC<{ + children: React.ReactNode; + is_open: boolean; + title: string; + height: string; +}> & { + Body?: React.FC<{ + children: React.ReactNode; + }>; + Footer?: React.FC<{ + children: React.ReactNode; + }>; +}; + +jest.mock('@deriv/stores', () => ({ + ...jest.requireActual('@deriv/stores'), + observer: jest.fn(x => x), + useStore: jest.fn(() => ({ + ui: { + is_mobile: true, + }, + })), +})); + +jest.mock('@deriv/shared', () => ({ + ...jest.requireActual('@deriv/shared'), + isMobile: jest.fn(() => true), +})); + +jest.mock('@deriv/components', () => { + const original_module = jest.requireActual('@deriv/components'); + const Modal: TModal = jest.fn(({ children, is_open, title, height }) => { + if (is_open) { + return ( +
+

{title}

+

{height}

+ {children} +
+ ); + } + return null; + }); + Modal.Body = jest.fn(({ children }) =>
{children}
); + Modal.Footer = jest.fn(({ children }) =>
{children}
); + + return { + ...original_module, + Modal, + }; +}); +describe('', () => { + let mocked_props: React.ComponentProps; + const history = createBrowserHistory(); + const renderWithRouter = (component: React.ReactElement) => { + return render({component}); + }; + + beforeEach(() => { + mocked_props = { + onConfirm: jest.fn(), + is_visible: true, + }; + }); + it('height should be auto if isMobile is true', () => { + render(); + expect(screen.getByText('auto')).toBeInTheDocument(); + }); + it('height should be 220px if isMobile is false', () => { + (useStore as jest.Mock).mockReturnValue({ + ui: { + is_mobile: false, + }, + }); + render(); + expect(screen.getByText('220px')).toBeInTheDocument(); + }); + it('should render modal title, modal description, and submit button.', () => { + render(); + expect(screen.getByText(/account verification required/i)).toBeInTheDocument(); + expect( + screen.getByText( + /Please submit your proof of identity and proof of address to verify your account and continue trading./i + ) + ).toBeInTheDocument(); + expect(screen.getByText(/submit proof/i)).toBeInTheDocument(); + }); + it('should return null when is_visible is false', () => { + mocked_props.is_visible = false; + const { container } = render(); + expect(container).toBeEmptyDOMElement(); + }); + it('should navigate to proof_of_identity url on clicking on submit button', () => { + renderWithRouter(); + const submit_proof_button = screen.getByText(/submit proof/i); + userEvent.click(submit_proof_button); + expect(history.location.pathname).toBe(routes.proof_of_identity); + }); +}); diff --git a/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/authorization-required-modal.spec.tsx b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/authorization-required-modal.spec.tsx new file mode 100644 index 000000000000..795173213716 --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/authorization-required-modal.spec.tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import { screen, render } from '@testing-library/react'; +import AuthorizationRequiredModal from '../authorization-required-modal'; +import { redirectToLogin, redirectToSignUp } from '@deriv/shared'; +import userEvent from '@testing-library/user-event'; + +type TModal = React.FC<{ + children: React.ReactNode; + is_open: boolean; + title: string; +}> & { + Body?: React.FC<{ + children: React.ReactNode; + }>; + Footer?: React.FC<{ + children: React.ReactNode; + }>; +}; + +jest.mock('@deriv/components', () => { + const original_module = jest.requireActual('@deriv/components'); + const Modal: TModal = jest.fn(({ children, is_open, title }) => { + if (is_open) { + return ( +
+

{title}

+ {children} +
+ ); + } + return null; + }); + Modal.Body = jest.fn(({ children }) =>
{children}
); + Modal.Footer = jest.fn(({ children }) =>
{children}
); + + return { + ...original_module, + Modal, + }; +}); + +jest.mock('@deriv/shared', () => ({ + ...jest.requireActual('@deriv/shared'), + redirectToLogin: jest.fn(), + redirectToSignUp: jest.fn(), +})); + +describe('', () => { + const mocked_props = { + is_visible: true, + toggleModal: jest.fn(), + is_logged_in: true, + is_appstore: true, + }; + + it('modal title, modal description, log in button, and signup button to be rendered', () => { + render(); + expect(screen.getByText(/start trading with us/i)).toBeInTheDocument(); + expect(screen.getByText(/Log in or create a free account to place a trade/i)).toBeInTheDocument(); + expect(screen.getByText('Log in')).toBeInTheDocument(); + expect(screen.getByText(/create free account/i)).toBeInTheDocument(); + }); + it('redirectToLogin should be called when Log in button is clicked', () => { + render(); + userEvent.click(screen.getByText('Log in')); + expect(redirectToLogin).toHaveBeenCalled(); + }); + it('redirectToSignUp should be called when Log in button is clicked', () => { + render(); + userEvent.click(screen.getByText(/create free account/i)); + expect(redirectToSignUp).toHaveBeenCalled(); + }); + it('should return null when is_visible is false', () => { + mocked_props.is_visible = false; + const { container } = render(); + expect(container).toBeEmptyDOMElement(); + }); +}); diff --git a/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/company-wide-limit-exceeded-modal.spec.tsx b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/company-wide-limit-exceeded-modal.spec.tsx new file mode 100644 index 000000000000..8c839fe66352 --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/company-wide-limit-exceeded-modal.spec.tsx @@ -0,0 +1,68 @@ +import React from 'react'; +import { screen, render } from '@testing-library/react'; +import CompanyWideLimitExceededModal from '../company-wide-limit-exceeded-modal'; + +type TModal = React.FC<{ + children: React.ReactNode; + is_open: boolean; + title: string; +}> & { + Body?: React.FC<{ + children: React.ReactNode; + }>; + Footer?: React.FC<{ + children: React.ReactNode; + }>; +}; + +jest.mock('@deriv/components', () => { + const original_module = jest.requireActual('@deriv/components'); + const Modal: TModal = jest.fn(({ children, is_open, title }) => { + if (is_open) { + return ( +
+

{title}

+ {children} +
+ ); + } + return null; + }); + Modal.Body = jest.fn(({ children }) =>
{children}
); + Modal.Footer = jest.fn(({ children }) =>
{children}
); + + return { + ...original_module, + Modal, + }; +}); + +jest.mock('@deriv/stores', () => ({ + ...jest.requireActual('@deriv/stores'), + observer: jest.fn(x => x), + useStore: jest.fn(() => ({ + ui: { + is_mobile: false, + }, + })), +})); + +describe('', () => { + const mocked_props = { + is_visible: true, + onConfirm: jest.fn(), + }; + it('should render modal title, modal description, and modal button.', () => { + render(); + expect(screen.getByText(/purchase error/i)).toBeInTheDocument(); + expect( + screen.getByText(/no further trading is allowed on this contract type for the current trading session./i) + ).toBeInTheDocument(); + expect(screen.getByText(/ok/i)).toBeInTheDocument(); + }); + it('should return null when is_visible is false', () => { + mocked_props.is_visible = false; + const { container } = render(); + expect(container).toBeEmptyDOMElement(); + }); +}); diff --git a/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/constants.spec.ts b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/constants.spec.ts new file mode 100644 index 000000000000..af82277e5c9f --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/constants.spec.ts @@ -0,0 +1,19 @@ +import { getTitle } from '../constants'; + +describe('getTitle', () => { + it('should return "Purchase Error" if input is buy', () => { + expect(getTitle('buy')).toBe('Purchase Error'); + }); + it('should return "Deal Cancellation Error" if input is cancel', () => { + expect(getTitle('cancel')).toBe('Deal Cancellation Error'); + }); + it('should return "Contract Update Error" if input is buy', () => { + expect(getTitle('contract_update')).toBe('Contract Update Error'); + }); + it('should return "Sell Error" if input is buy', () => { + expect(getTitle('sell')).toBe('Sell Error'); + }); + it('should return "Error" if input is not a defined type', () => { + expect(getTitle('test')).toBe('Error'); + }); +}); diff --git a/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/insufficient-balance-modal.spec.tsx b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/insufficient-balance-modal.spec.tsx new file mode 100644 index 000000000000..fe4cdde3c975 --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/insufficient-balance-modal.spec.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { screen, render } from '@testing-library/react'; +import InsufficientBalanceModal from '../insufficient-balance-modal'; +import { createBrowserHistory } from 'history'; +import { Router } from 'react-router-dom'; +import { routes } from '@deriv/shared'; +import userEvent from '@testing-library/user-event'; + +type TModal = React.FC<{ + children: React.ReactNode; + is_open: boolean; + title: string; +}> & { + Body?: React.FC<{ + children: React.ReactNode; + }>; + Footer?: React.FC<{ + children: React.ReactNode; + }>; +}; + +jest.mock('@deriv/stores', () => ({ + ...jest.requireActual('@deriv/stores'), + observer: jest.fn(x => x), + useStore: jest.fn(() => ({ + ui: { + is_mobile: false, + }, + })), +})); + +jest.mock('@deriv/components', () => { + const original_module = jest.requireActual('@deriv/components'); + const Modal: TModal = jest.fn(({ children, is_open, title }) => { + if (is_open) { + return ( +
+

{title}

+ {children} +
+ ); + } + return null; + }); + Modal.Body = jest.fn(({ children }) =>
{children}
); + Modal.Footer = jest.fn(({ children }) =>
{children}
); + + return { + ...original_module, + Modal, + }; +}); + +describe('', () => { + const mocked_props = { + is_virtual: true, + is_visible: true, + message: 'test', + toggleModal: jest.fn(), + }; + + const history = createBrowserHistory(); + const renderWithRouter = (component: React.ReactElement) => { + return render({component}); + }; + + it('modal title, and modal description should be rendered', () => { + renderWithRouter(); + expect(screen.getByText(/insufficient balance/i)).toBeInTheDocument(); + expect(screen.getByText(/test/i)).toBeInTheDocument(); + }); + it('button text should be OK if is_virtual is true and toggleModal should be called if user clicks on the button', () => { + renderWithRouter(); + const button = screen.getByText(/ok/i); + expect(button).toBeInTheDocument(); + userEvent.click(button); + expect(mocked_props.toggleModal).toHaveBeenCalled(); + }); + it('button text should be "Deposit now" if is_virtual is false and should navigate to bla bla if you click on the button', () => { + mocked_props.is_virtual = false; + renderWithRouter(); + const button = screen.getByText(/deposit now/i); + expect(button).toBeInTheDocument(); + userEvent.click(button); + expect(history.location.pathname).toBe(routes.cashier_deposit); + }); + it('should return null when is_visible is false', () => { + mocked_props.is_visible = false; + const { container } = renderWithRouter(); + expect(container).toBeEmptyDOMElement(); + }); +}); diff --git a/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/services-error-modal.spec.tsx b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/services-error-modal.spec.tsx new file mode 100644 index 000000000000..993d314439ae --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/__tests__/services-error-modal.spec.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import ServicesErrorModal from '../services-error-modal'; + +jest.mock('../authorization-required-modal', () => jest.fn(() => 'AuthorizationRequiredModal')); +jest.mock('../insufficient-balance-modal', () => jest.fn(() => 'InsufficientBalanceModal')); +jest.mock('../company-wide-limit-exceeded-modal', () => jest.fn(() => 'CompanyWideLimitExceededModal')); +jest.mock('../account-verification-required-modal', () => jest.fn(() => 'AccountVerificationRequiredModal')); + +type TModal = { + (): JSX.Element; + Body?: React.FC; + Footer?: React.FC; +}; +jest.mock('@deriv/components', () => { + const original_module = jest.requireActual('@deriv/components'); + const Modal: TModal = jest.fn(() =>
Modal
); + Modal.Body = jest.fn(() =>
); + Modal.Footer = jest.fn(() =>
); + return { + ...original_module, + Modal, + }; +}); + +describe('', () => { + const modal_props = { + is_visible: true, + onConfirm: jest.fn(), + is_logged_in: true, + }; + it('Should return null if code or message is missing', () => { + const services_error_mock = { + code: '', + message: '', + type: '', + }; + const { container } = render( + + ); + expect(container).toBeEmptyDOMElement(); + }); + + it('AuthorizationRequiredModal should render when code is AuthorizationRequired', () => { + const services_error_mock = { + code: 'AuthorizationRequired', + message: 'AuthorizationRequired', + type: '', + }; + render(); + expect(screen.getByText('AuthorizationRequiredModal')).toBeInTheDocument(); + }); + + it('InsufficientBalanceModal should render when code is InsufficientBalance', () => { + const services_error_mock = { + code: 'InsufficientBalance', + message: 'InsufficientBalance', + type: '', + }; + render(); + expect(screen.getByText('InsufficientBalanceModal')).toBeInTheDocument(); + }); + + it('CompanyWideLimitExceededModal should render when code is CompanyWideLimitExceeded', () => { + const services_error_mock = { + code: 'CompanyWideLimitExceeded', + message: 'CompanyWideLimitExceeded', + type: '', + }; + render(); + expect(screen.getByText('CompanyWideLimitExceededModal')).toBeInTheDocument(); + }); + + it('AccountVerificationRequiredModal should render when code is PleaseAuthenticate', () => { + const services_error_mock = { + code: 'PleaseAuthenticate', + message: 'PleaseAuthenticate', + type: '', + }; + render(); + expect(screen.getByText('AccountVerificationRequiredModal')).toBeInTheDocument(); + }); + + it('Default case should render when code is not specified in switch case', () => { + const services_error_mock = { + code: 'Default Error', + message: 'Default Error', + title: 'Default Error', + type: '', + }; + render(); + expect(screen.getByText('Modal')).toBeInTheDocument(); + }); +}); diff --git a/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/account-verification-required-modal.tsx b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/account-verification-required-modal.tsx new file mode 100644 index 000000000000..d04e470a271a --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/account-verification-required-modal.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { Button, Modal } from '@deriv/components'; +import { routes } from '@deriv/shared'; +import { observer, useStore } from '@deriv/stores'; +import { localize, Localize } from '@deriv/translations'; + +type TAccountVerificationRequiredModalProps = { + is_visible: boolean; + onConfirm: () => void; +}; + +const AccountVerificationRequiredModal = observer( + ({ is_visible, onConfirm }: TAccountVerificationRequiredModalProps) => { + const history = useHistory(); + const { + ui: { is_mobile }, + } = useStore(); + return ( + + + + + +
+ +
+
+ ); + } +); + +export default AccountVerificationRequiredModal; diff --git a/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/authorization-required-modal.tsx b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/authorization-required-modal.tsx new file mode 100644 index 000000000000..69779bab16ea --- /dev/null +++ b/packages/reports/src/Components/Elements/Modals/ServicesErrorModal/authorization-required-modal.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { Button, Modal } from '@deriv/components'; +import { getLanguage, localize } from '@deriv/translations'; +import { redirectToLogin, redirectToSignUp } from '@deriv/shared'; + +type TAuthorizationRequiredModal = { + is_visible: boolean; + toggleModal: () => void; + is_appstore?: boolean; + is_logged_in: boolean; +}; + +const AuthorizationRequiredModal = ({ + is_visible, + toggleModal, + is_appstore, + is_logged_in, +}: TAuthorizationRequiredModal) => ( + + {localize('Log in or create a free account to place a trade.')} + + + +
+ )) +); +jest.mock('../../Elements/Modals/ServicesErrorModal', () => + jest.fn(props => ( +
+
Services error modal
+ +
+ )) +); + +window.open = jest.fn(); + +describe('TradeModals', () => { + const mockTradeModals = (mocked_store: TCoreStores) => { + return ( + + + + ); + }; + + it('should render modal', () => { + const mock_root_store = mockStore({}); + + render(mockTradeModals(mock_root_store)); + + expect(screen.getByText('Market unavailable modal')).toBeInTheDocument(); + expect(screen.getByText('Services error modal')).toBeInTheDocument(); + }); + it('should call function marketUnavailableOnConfirm if button onConfirm in MarketUnavailableModal component was clicked', () => { + const mock_root_store = mockStore({}); + + render(mockTradeModals(mock_root_store)); + userEvent.click(screen.getByText('onConfirm market')); + + expect(mock_root_store.ui.setHasOnlyForwardingContracts).toHaveBeenCalled(); + }); + it('should call function marketUnavailableOnCancel if button onCancel in MarketUnavailableModal component was clicked', () => { + const mock_root_store = mockStore({}); + + render(mockTradeModals(mock_root_store)); + userEvent.click(screen.getByText('onCancel market')); + + expect(mock_root_store.ui.setHasOnlyForwardingContracts).toHaveBeenCalled(); + }); + it('should call function servicesErrorModalOnConfirm if button onConfirm in ServicesErrorModal component was clicked', () => { + const mock_root_store = mockStore({}); + + render(mockTradeModals(mock_root_store)); + userEvent.click(screen.getByText('onConfirm services')); + + expect(mock_root_store.ui.toggleServicesErrorModal).toHaveBeenCalled(); + }); + it('should call function servicesErrorModalOnConfirm and clearPurchaseInfo and requestProposal if button onConfirm in ServicesErrorModal component was clicked and type of services_error is equal to buy', () => { + const mock_root_store = mockStore({ + common: { + services_error: { + code: 'test', + message: 'test', + type: 'buy', + }, + }, + }); + + render(mockTradeModals(mock_root_store)); + userEvent.click(screen.getByText('onConfirm services')); + + expect(mock_root_store.ui.toggleServicesErrorModal).toHaveBeenCalled(); + }); +}); diff --git a/packages/reports/src/Components/Modals/index.ts b/packages/reports/src/Components/Modals/index.ts new file mode 100644 index 000000000000..af8b1307fab3 --- /dev/null +++ b/packages/reports/src/Components/Modals/index.ts @@ -0,0 +1,3 @@ +import TradeModals from './trade-modals'; + +export default TradeModals; diff --git a/packages/reports/src/Components/Modals/trade-modals.tsx b/packages/reports/src/Components/Modals/trade-modals.tsx new file mode 100644 index 000000000000..2994644cbf76 --- /dev/null +++ b/packages/reports/src/Components/Modals/trade-modals.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { getUrlSmartTrader } from '@deriv/shared'; +import MarketUnavailableModal from '../Elements/Modals/MarketUnavailableModal'; +import ServicesErrorModal from '../Elements/Modals/ServicesErrorModal'; +import AccountVerificationPendingModal from '../Elements/Modals/AccountVerificationPendingModal'; +import { observer, useStore } from '@deriv/stores'; + +const TradeModals = observer(() => { + const { ui, client, common } = useStore(); + const { is_virtual, is_logged_in } = client; + + const { services_error } = common; + const { + is_mf_verification_pending_modal_visible, + is_services_error_visible, + setHasOnlyForwardingContracts, + setIsMFVericationPendingModal, + toggleServicesErrorModal, + } = ui; + const resetToPreviousMarket = () => { + setHasOnlyForwardingContracts(false); + }; + + const marketUnavailableOnConfirm = () => { + resetToPreviousMarket(); + }; + + const marketUnavailableOnCancel = () => { + window.open(getUrlSmartTrader()); + resetToPreviousMarket(); + }; + + const servicesErrorModalOnConfirm = () => { + toggleServicesErrorModal(false); + }; + + return ( + + + + + + setIsMFVericationPendingModal(false)} + /> + + ); +}); + +export default TradeModals; diff --git a/packages/reports/src/app.tsx b/packages/reports/src/app.tsx index fa9f31db13d0..549fb71a5c1e 100644 --- a/packages/reports/src/app.tsx +++ b/packages/reports/src/app.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import Loadable from 'react-loadable'; import Routes from 'Containers/routes'; import ReportsProviders from './reports-providers'; import 'Sass/app.scss'; @@ -10,10 +11,16 @@ type TAppProps = { }; }; +const TradeModals = Loadable({ + loader: () => import(/* webpackChunkName: "trade-modals", webpackPrefetch: true */ './Components/Modals'), + loading: () => null, +}); + const App = ({ passthrough }: TAppProps) => { return ( + ); };