diff --git a/packages/components/src/components/dialog/dialog.tsx b/packages/components/src/components/dialog/dialog.tsx index 7bd402d56707..85e9a8c5fa0c 100644 --- a/packages/components/src/components/dialog/dialog.tsx +++ b/packages/components/src/components/dialog/dialog.tsx @@ -26,7 +26,7 @@ type TDialog = { onConfirm: () => void; onEscapeButtonCancel?: () => void; portal_element_id?: string; - title?: string | JSX.Element; + title?: React.ReactNode; }; const Dialog = ({ diff --git a/packages/components/src/components/dropdown/dropdown.tsx b/packages/components/src/components/dropdown/dropdown.tsx index a76d31aa30c8..021e10fc2762 100644 --- a/packages/components/src/components/dropdown/dropdown.tsx +++ b/packages/components/src/components/dropdown/dropdown.tsx @@ -26,6 +26,7 @@ type TDropdown = { }; has_symbol?: boolean; hint?: string; + id?: string; initial_offset?: number; initial_height_offset?: number; is_align_text_left?: boolean; diff --git a/packages/components/src/components/input-wth-checkbox/input-with-checkbox.tsx b/packages/components/src/components/input-wth-checkbox/input-with-checkbox.tsx index 736ee2891b8a..7e783b0b0355 100644 --- a/packages/components/src/components/input-wth-checkbox/input-with-checkbox.tsx +++ b/packages/components/src/components/input-wth-checkbox/input-with-checkbox.tsx @@ -29,11 +29,11 @@ type TInputWithCheckbox = { e: React.ChangeEvent | { target: { name: string; value: number | string | boolean } } ) => void; setCurrentFocus: (name: string | null) => void; - tooltip_label?: string; + tooltip_label?: React.ReactNode; tooltip_alignment?: TPosition; error_message_alignment: string; value: number | string; - is_disabled: boolean; + is_disabled?: boolean; }; const InputWithCheckbox = ({ addToast, diff --git a/packages/stores/src/mockStore.ts b/packages/stores/src/mockStore.ts index 4bdc35cdbc13..8d8bf554af65 100644 --- a/packages/stores/src/mockStore.ts +++ b/packages/stores/src/mockStore.ts @@ -355,11 +355,14 @@ const mock = (): TStores & { is_mock: boolean } => { notification_messages_ui: jest.fn(), openPositionsDrawer: jest.fn(), openRealAccountSignup: jest.fn(), + onChangeUiStore: jest.fn(), + setChartCountdown: jest.fn(), setIsWalletModalVisible: jest.fn(), setHasOnlyForwardingContracts: jest.fn(), setIsClosingCreateRealAccountModal: jest.fn(), setMobileLanguageMenuOpen: jest.fn(), setRealAccountSignupEnd: jest.fn(), + setPromptHandler: jest.fn(), setPurchaseState: jest.fn(), setAppContentsScrollRef: jest.fn(), shouldNavigateAfterChooseCrypto: jest.fn(), @@ -370,8 +373,8 @@ const mock = (): TStores & { is_mock: boolean } => { toggleSetCurrencyModal: jest.fn(), addToast: jest.fn(), removeToast: jest.fn(), - reports_route_tab_index: 1, resetPurchaseStates: jest.fn(), + reports_route_tab_index: 1, should_show_cancellation_warning: false, toggleCancellationWarning: jest.fn(), toggleUnsupportedContractModal: jest.fn(), @@ -405,6 +408,7 @@ const mock = (): TStores & { is_mock: boolean } => { is_reset_trading_password_modal_visible: false, setResetTradingPasswordModalOpen: jest.fn(), vanilla_trade_type: 'VANILLALONGCALL', + is_chart_countdown_visible: false, is_additional_kyc_info_modal_open: false, toggleAdditionalKycInfoModal: jest.fn(), is_kyc_information_submitted_modal_open: false, @@ -516,11 +520,12 @@ const mock = (): TStores & { is_mock: boolean } => { is_accumulator: false, is_multiplier: false, is_turbos: false, - onHoverPosition: jest.fn(), onBuyResponse: jest.fn(), + onHoverPosition: jest.fn(), onClickCancel: jest.fn(), onClickSell: jest.fn(), onMount: jest.fn(), + onUnmount: jest.fn(), open_accu_contract: null, positions: [], removePositionById: jest.fn(), @@ -537,6 +542,7 @@ const mock = (): TStores & { is_mock: boolean } => { clearError: jest.fn(), contracts: [], error_message: '', + filtered_contracts: [], getContractById: jest.fn(), granularity: 0, has_crossed_accu_barriers: false, @@ -589,6 +595,8 @@ const mock = (): TStores & { is_mock: boolean } => { is_digit_contract: false, is_ended: false, }, + removeErrorMessage: jest.fn(), + error_message: '', }, chart_barrier_store: {}, active_symbols: { diff --git a/packages/stores/types.ts b/packages/stores/types.ts index cdb1ae82b0ef..ca0cac6d97d2 100644 --- a/packages/stores/types.ts +++ b/packages/stores/types.ts @@ -574,6 +574,7 @@ type TUiStore = { is_wallet_modal_visible: boolean; is_chart_asset_info_visible?: boolean; is_chart_layout_default: boolean; + is_chart_countdown_visible: boolean; is_closing_create_real_account_modal: boolean; is_kyc_information_submitted_modal_open: boolean; is_dark_mode_on: boolean; @@ -594,7 +595,9 @@ type TUiStore = { openRealAccountSignup: ( value: 'maltainvest' | 'svg' | 'add_crypto' | 'choose' | 'add_fiat' | 'set_currency' | 'manage' ) => void; + onChangeUiStore: ({ name, value }: { name: string; value: number | null }) => void; notification_messages_ui: React.ElementType; + setChartCountdown: (value: boolean) => void; populateFooterExtensions: ( footer_extensions: | [ @@ -618,6 +621,10 @@ type TUiStore = { setRealAccountSignupEnd: (status: boolean) => void; setPurchaseState: (index: number) => void; sub_section_index: number; + setPromptHandler: ( + condition: boolean, + cb?: (() => void) | ((route_to: RouteComponentProps['location'], action: string) => boolean) + ) => void; setSubSectionIndex: (index: number) => void; shouldNavigateAfterChooseCrypto: (value: Omit | TRoutes) => void; toggleAccountsDialog: () => void; @@ -683,6 +690,7 @@ type TPortfolioStore = { onClickCancel: (contract_id?: number) => void; onClickSell: (contract_id?: number) => void; onMount: () => void; + onUnmount: () => void; open_accu_contract: TPortfolioPosition | null; positions: TPortfolioPosition[]; removePositionById: (contract_id?: number) => void; @@ -758,6 +766,7 @@ type TContractTradeStore = { clearError: () => void; contracts: TContractStore[]; error_message: string; + filtered_contracts: TPortfolioPosition[]; getContractById: (contract_id?: number) => TContractStore; granularity: null | number; has_crossed_accu_barriers: boolean; @@ -765,17 +774,7 @@ type TContractTradeStore = { last_contract: TContractStore | Record; markers_array: Array<{ type: string; - contract_info: { - accu_barriers_difference: - | boolean - | { - top: string; - bottom: string; - font: string; - }; - has_crossed_accu_barriers: boolean; - is_accumulator_trade_without_contract: boolean; - }; + contract_info: TPortfolioPosition['contract_info']; key: string; price_array: [string, string]; epoch_array: [number]; @@ -939,6 +938,8 @@ type TContractReplay = { is_digit_contract: boolean; is_ended: boolean; }; + removeErrorMessage: () => void; + error_message: string; }; type TGtmStore = { is_gtm_applicable: boolean; diff --git a/packages/trader/src/App/Components/Elements/Errors/error-component.tsx b/packages/trader/src/App/Components/Elements/Errors/error-component.tsx index b5485b0791c9..9ecb286b1f00 100644 --- a/packages/trader/src/App/Components/Elements/Errors/error-component.tsx +++ b/packages/trader/src/App/Components/Elements/Errors/error-component.tsx @@ -4,11 +4,11 @@ import { routes } from '@deriv/shared'; import { localize } from '@deriv/translations'; type TErrorComponent = { - header: string; + header: React.ReactNode; message: React.ReactNode; is_dialog: boolean; redirect_label: string; - redirectOnClick: () => void; + redirectOnClick: (() => void) | null; should_show_refresh: boolean; }; diff --git a/packages/trader/src/App/Components/Routes/__tests__/helpers.spec.js b/packages/trader/src/App/Components/Routes/__tests__/helpers.spec.ts similarity index 91% rename from packages/trader/src/App/Components/Routes/__tests__/helpers.spec.js rename to packages/trader/src/App/Components/Routes/__tests__/helpers.spec.ts index ef0eebbbfef0..d4f6ec74beaa 100644 --- a/packages/trader/src/App/Components/Routes/__tests__/helpers.spec.js +++ b/packages/trader/src/App/Components/Routes/__tests__/helpers.spec.ts @@ -1,4 +1,3 @@ -import React from 'react'; import * as Helpers from '../helpers'; import { routes } from '@deriv/shared'; import getRoutesConfig from '../../../Constants/routes-config'; @@ -23,9 +22,9 @@ describe('Helpers', () => { }); it('should return route_info when path is in routes_config and is not nested', () => { const result = Helpers.findRouteByPath(routes.trade, getRoutesConfig()); - expect(result.path).toBe(routes.trade); - expect(result.exact).toBe(true); - expect(result.component).toBe(Trade); + expect(result?.path).toBe(routes.trade); + expect(result?.exact).toBe(true); + expect(result?.component).toBe(Trade); }); }); @@ -46,7 +45,7 @@ describe('Helpers', () => { describe('getPath', () => { it('should return param values in params as a part of path', () => { - expect(Helpers.getPath('/contract/:contract_id', { contract_id: 37511105068 })).toBe( + expect(Helpers.getPath('/contract/:contract_id', { contract_id: '37511105068' })).toBe( '/contract/37511105068' ); expect( @@ -63,7 +62,7 @@ describe('Helpers', () => { describe('getContractPath', () => { it('should return the path of contract with contract_id passed', () => { - expect(Helpers.getContractPath(1234)).toBe('/contract/1234'); + expect(Helpers.getContractPath('1234')).toBe('/contract/1234'); }); }); }); diff --git a/packages/trader/src/App/Components/Routes/binary-link.jsx b/packages/trader/src/App/Components/Routes/binary-link.tsx similarity index 81% rename from packages/trader/src/App/Components/Routes/binary-link.jsx rename to packages/trader/src/App/Components/Routes/binary-link.tsx index 2a4434fd6300..71e310ec7dc9 100644 --- a/packages/trader/src/App/Components/Routes/binary-link.jsx +++ b/packages/trader/src/App/Components/Routes/binary-link.tsx @@ -1,13 +1,19 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { NavLink } from 'react-router-dom'; import { findRouteByPath, normalizePath } from './helpers'; import getRoutesConfig from '../../Constants/routes-config'; +type TBinaryLinkProps = React.PropsWithChildren<{ + active_class?: string; + className?: string; + to?: string; + onClick?: () => void; +}>; + // TODO: solve circular dependency problem // when binary link is imported into components present in routes config // or into their descendants -const BinaryLink = ({ active_class = '', to, children, ...props }) => { +const BinaryLink = ({ active_class = '', to, children, ...props }: TBinaryLinkProps) => { const path = normalizePath(to); const route = findRouteByPath(path, getRoutesConfig()); @@ -32,10 +38,4 @@ const BinaryLink = ({ active_class = '', to, children, ...props }) => { ); }; -BinaryLink.propTypes = { - active_class: PropTypes.string, - children: PropTypes.oneOfType([PropTypes.object, PropTypes.array, PropTypes.string]), - to: PropTypes.string, -}; - export default BinaryLink; diff --git a/packages/trader/src/App/Components/Routes/binary-routes.jsx b/packages/trader/src/App/Components/Routes/binary-routes.jsx deleted file mode 100644 index 0bce70a4cc0d..000000000000 --- a/packages/trader/src/App/Components/Routes/binary-routes.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import { Switch } from 'react-router-dom'; -import getRoutesConfig from 'App/Constants/routes-config'; -import RouteWithSubRoutes from './route-with-sub-routes.jsx'; - -const BinaryRoutes = props => ( - }> - - {getRoutesConfig().map((route, idx) => ( - - ))} - - -); - -export default BinaryRoutes; diff --git a/packages/trader/src/App/Components/Routes/binary-routes.tsx b/packages/trader/src/App/Components/Routes/binary-routes.tsx new file mode 100644 index 000000000000..c53c63571d19 --- /dev/null +++ b/packages/trader/src/App/Components/Routes/binary-routes.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Switch } from 'react-router-dom'; +import getRoutesConfig from 'App/Constants/routes-config'; +import { TBinaryRoutesProps, TRouteConfig } from 'Types'; +import RouteWithSubRoutes from './route-with-sub-routes'; + +const BinaryRoutes = (props: TBinaryRoutesProps) => ( + }> + + {getRoutesConfig().map((route: TRouteConfig, index) => ( + /* Index is the only thing that can be used for the key here because the only other property + that can be used as a key and available in every route is a localized title returned from getTitle() which, + when used, causes severe bugs upon switching between languages! */ + + ))} + + +); + +export default BinaryRoutes; diff --git a/packages/trader/src/App/Components/Routes/helpers.js b/packages/trader/src/App/Components/Routes/helpers.js deleted file mode 100644 index 8d8bcc421c1d..000000000000 --- a/packages/trader/src/App/Components/Routes/helpers.js +++ /dev/null @@ -1,37 +0,0 @@ -import { matchPath } from 'react-router'; -import { routes } from '@deriv/shared'; - -export const normalizePath = path => (/^\//.test(path) ? path : `/${path || ''}`); // Default to '/' - -export const findRouteByPath = (path, routes_config) => { - let result; - - routes_config.some(route_info => { - let match_path; - try { - match_path = matchPath(path, route_info); - } catch (e) { - if (/undefined/.test(e.message)) { - return undefined; - } - } - - if (match_path) { - result = route_info; - return true; - } else if (route_info.routes) { - result = findRouteByPath(path, route_info.routes); - return result; - } - return false; - }); - - return result; -}; - -export const isRouteVisible = (route, is_logged_in) => !(route && route.is_authenticated && !is_logged_in); - -export const getPath = (route_path, params = {}) => - Object.keys(params).reduce((p, name) => p.replace(`:${name}`, params[name]), route_path); - -export const getContractPath = contract_id => getPath(routes.contract, { contract_id }); diff --git a/packages/trader/src/App/Components/Routes/helpers.ts b/packages/trader/src/App/Components/Routes/helpers.ts new file mode 100644 index 000000000000..f846313aa28d --- /dev/null +++ b/packages/trader/src/App/Components/Routes/helpers.ts @@ -0,0 +1,39 @@ +import { matchPath, RouteProps } from 'react-router'; +import { routes } from '@deriv/shared'; +import { TRouteConfig } from 'Types'; + +export const normalizePath = (path = '') => (path.startsWith('/') ? path : `/${path || ''}`); // Default to '/' + +export const findRouteByPath = (path: string, routes_config?: TRouteConfig[]): RouteProps | undefined => { + let result: RouteProps | undefined; + + routes_config?.some(route_info => { + let match_path; + try { + match_path = matchPath(path, route_info); + } catch (e: unknown) { + if (/undefined/.test((e as Error).message)) { + return undefined; + } + } + + if (match_path) { + result = route_info; + return true; + } else if (route_info.routes) { + result = findRouteByPath(path, route_info.routes); + return result; + } + return false; + }); + + return result; +}; + +export const isRouteVisible = (route?: TRouteConfig, is_logged_in?: boolean) => + !(route?.is_authenticated && !is_logged_in); + +export const getPath = (route_path: string, params: { [key: string]: string } = {}) => + Object.keys(params).reduce((p, name) => p.replace(`:${name}`, params[name]), route_path); + +export const getContractPath = (contract_id = '') => getPath(routes.contract, { contract_id }); diff --git a/packages/trader/src/App/Components/Routes/index.js b/packages/trader/src/App/Components/Routes/index.js deleted file mode 100644 index 5d349b8e17ee..000000000000 --- a/packages/trader/src/App/Components/Routes/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import BinaryLink from './binary-link.jsx'; -import RouteWithSubRoutes from './route-with-sub-routes.jsx'; -import BinaryRoutes from './binary-routes.jsx'; - -export * from './helpers'; -export { BinaryLink, RouteWithSubRoutes }; -export default BinaryRoutes; diff --git a/packages/trader/src/App/Components/Routes/index.ts b/packages/trader/src/App/Components/Routes/index.ts new file mode 100644 index 000000000000..ecff56bd3670 --- /dev/null +++ b/packages/trader/src/App/Components/Routes/index.ts @@ -0,0 +1,7 @@ +import BinaryLink from './binary-link'; +import RouteWithSubRoutes from './route-with-sub-routes'; +import BinaryRoutes from './binary-routes'; + +export * from './helpers'; +export { BinaryLink, RouteWithSubRoutes }; +export default BinaryRoutes; diff --git a/packages/trader/src/App/Components/Routes/route-with-sub-routes.jsx b/packages/trader/src/App/Components/Routes/route-with-sub-routes.tsx similarity index 72% rename from packages/trader/src/App/Components/Routes/route-with-sub-routes.jsx rename to packages/trader/src/App/Components/Routes/route-with-sub-routes.tsx index 4c4c4f9213f8..a385cf7cca15 100644 --- a/packages/trader/src/App/Components/Routes/route-with-sub-routes.jsx +++ b/packages/trader/src/App/Components/Routes/route-with-sub-routes.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Redirect, Route } from 'react-router-dom'; +import { Redirect, Route, RouteComponentProps } from 'react-router-dom'; import { alternateLinkTagChange, canonicalLinkTagChange, @@ -11,18 +11,21 @@ import { } from '@deriv/shared'; import { getLanguage } from '@deriv/translations'; import Page404 from 'Modules/Page404'; +import { TBinaryRoutesProps, TRouteConfig } from 'Types'; -const RouteWithSubRoutes = route => { - const validateRoute = pathname => { +type TRouteWithSubRoutesProps = TRouteConfig & TBinaryRoutesProps; + +const RouteWithSubRoutes = (route: TRouteWithSubRoutesProps) => { + const validateRoute = (pathname: string) => { if (pathname === '') return true; if (route.path?.includes(':')) { const static_pathname = pathname.substring(0, pathname.lastIndexOf('/') + 1); return static_pathname === route.path.substring(0, route.path.indexOf(':')); } - return route.path === pathname || !!(route.routes && route.routes.find(r => pathname === r.path)); + return route.path === pathname || !!route.routes?.find(r => pathname === r.path); }; - const renderFactory = props => { + const renderFactory = (props: RouteComponentProps) => { let result = null; const pathname = removeBranchName(location.pathname).replace(/\/$/, ''); @@ -42,17 +45,16 @@ const RouteWithSubRoutes = route => { } else { const default_subroute = route.routes ? route.routes.find(r => r.default) : {}; const has_default_subroute = !isEmptyObject(default_subroute); - + const RouteComponent = route.component as React.ElementType; result = ( - {has_default_subroute && pathname === route.path && } - {is_valid_route ? : } + {has_default_subroute && pathname === route.path && } + {is_valid_route ? : } ); } - // eslint-disable-next-line no-nested-ternary - const title = route.getTitle?.() || ''; + const title = route.getTitle?.() ?? ''; document.title = `${title} | ${default_title}`; alternateLinkTagChange(); diff --git a/packages/trader/src/App/Constants/routes-config.js b/packages/trader/src/App/Constants/routes-config.ts similarity index 64% rename from packages/trader/src/App/Constants/routes-config.js rename to packages/trader/src/App/Constants/routes-config.ts index 5bbbf238210e..52c7930825b2 100644 --- a/packages/trader/src/App/Constants/routes-config.js +++ b/packages/trader/src/App/Constants/routes-config.ts @@ -1,14 +1,24 @@ import React from 'react'; +import { RouteComponentProps } from 'react-router'; import { routes, moduleLoader } from '@deriv/shared'; import { localize } from '@deriv/translations'; import Trade from 'Modules/Trading'; +import { TRouteConfig } from 'Types'; -const ContractDetails = React.lazy(() => - moduleLoader(() => import(/* webpackChunkName: "contract" */ 'Modules/Contract')) +const ContractDetails = React.lazy( + () => + moduleLoader(() => import(/* webpackChunkName: "contract" */ 'Modules/Contract')) as Promise<{ + default: React.ComponentType; + }> ); // Error Routes -const Page404 = React.lazy(() => moduleLoader(() => import(/* webpackChunkName: "404" */ 'Modules/Page404'))); +const Page404 = React.lazy( + () => + moduleLoader(() => import(/* webpackChunkName: "404" */ 'Modules/Page404')) as Promise<{ + default: React.ComponentType>; + }> +); // Order matters const initRoutesConfig = () => { @@ -24,7 +34,7 @@ const initRoutesConfig = () => { ]; }; -let routesConfig; +let routesConfig: TRouteConfig[] | undefined; // For default page route if page/path is not found, must be kept at the end of routes_config array const route_default = { component: Page404, getTitle: () => localize('Error 404') }; diff --git a/packages/trader/src/App/Containers/Routes/routes.jsx b/packages/trader/src/App/Containers/Routes/routes.tsx similarity index 76% rename from packages/trader/src/App/Containers/Routes/routes.jsx rename to packages/trader/src/App/Containers/Routes/routes.tsx index 5a37e794281a..a4d09c3a96e9 100644 --- a/packages/trader/src/App/Containers/Routes/routes.jsx +++ b/packages/trader/src/App/Containers/Routes/routes.tsx @@ -1,6 +1,5 @@ -import PropTypes from 'prop-types'; import React from 'react'; -import { withRouter, matchPath } from 'react-router'; +import { withRouter, matchPath, RouteComponentProps } from 'react-router'; import Loadable from 'react-loadable'; import { UILoader } from '@deriv/components'; import { routes } from '@deriv/shared'; @@ -9,11 +8,29 @@ import getRoutesConfig from 'App/Constants/routes-config'; import { observer, useStore } from '@deriv/stores'; import { useTraderStore } from 'Stores/useTraderStores'; -const checkRoutingMatch = (route_list, path) => { +type TMatchPattern = { from: Array; to: Array }; + +type TRoutesProps = RouteComponentProps & { passthrough?: React.ComponentProps['passthrough'] }; + +type TTradePageMountingMiddlewareParams = { + action: string; + callback: (has_match: boolean) => void; + match_patterns: TMatchPattern[]; + path_from: string; + path_to: string; +}; + +const checkRoutingMatch = (route_list: Array, path = '') => { return route_list.some(route => !!matchPath(path, { path: route, exact: true })); }; -const tradePageMountingMiddleware = ({ path_from, path_to, action, match_patterns, callback }) => { +const tradePageMountingMiddleware = ({ + path_from, + path_to, + action, + match_patterns, + callback, +}: TTradePageMountingMiddlewareParams) => { if (action === 'PUSH' || action === 'POP') { // We use matchPath here because on route, there will be extra // parameters which matchPath takes into account. @@ -27,16 +44,16 @@ const tradePageMountingMiddleware = ({ path_from, path_to, action, match_pattern return true; }; -const Error = Loadable({ +const ErrorComponent = Loadable({ loader: () => import(/* webpackChunkName: "error-component" */ 'App/Components/Elements/Errors'), - loading: UILoader, + loading: () => , render(loaded, props) { const Component = loaded.default; return ; }, }); -const Routes = observer(({ history, passthrough }) => { +const Routes = observer(({ history, passthrough }: TRoutesProps) => { const { client, common, ui, portfolio } = useStore(); const { setSkipPrePostLifecycle: setTradeMountingPolicy } = useTraderStore(); const { error, has_error } = common; @@ -46,7 +63,7 @@ const Routes = observer(({ history, passthrough }) => { React.useEffect(() => { if (setPromptHandler) { - setPromptHandler(true, (route_to, action) => { + setPromptHandler(true, (route_to: RouteComponentProps['location'], action: string) => { // clears portfolio when we navigate to mt5 dashboard tradePageMountingMiddleware({ path_from: history.location.pathname, @@ -65,7 +82,7 @@ const Routes = observer(({ history, passthrough }) => { }, ], action, - callback: has_match => { + callback: (has_match: boolean) => { if (has_match) { onUnmountPortfolio(); } @@ -95,14 +112,9 @@ const Routes = observer(({ history, passthrough }) => { return () => onUnmountPortfolio(); }, [onUnmountPortfolio]); - if (has_error) return ; + if (has_error) return ; return ; }); -Routes.propTypes = { - history: PropTypes.object, - passthrough: PropTypes.object, -}; - export default withRouter(Routes); diff --git a/packages/trader/src/App/Containers/SettingsModal/index.js b/packages/trader/src/App/Containers/SettingsModal/index.js deleted file mode 100644 index 9dc28aad10ce..000000000000 --- a/packages/trader/src/App/Containers/SettingsModal/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export ChartSettings from './settings-chart.jsx'; -export PurchaseSettings from './settings-purchase.jsx'; diff --git a/packages/trader/src/App/Containers/SettingsModal/index.ts b/packages/trader/src/App/Containers/SettingsModal/index.ts new file mode 100644 index 000000000000..611ac4c6ca38 --- /dev/null +++ b/packages/trader/src/App/Containers/SettingsModal/index.ts @@ -0,0 +1,3 @@ +import ChartSettings from './settings-chart'; + +export default ChartSettings; diff --git a/packages/trader/src/App/Containers/SettingsModal/settings-chart.jsx b/packages/trader/src/App/Containers/SettingsModal/settings-chart.tsx similarity index 94% rename from packages/trader/src/App/Containers/SettingsModal/settings-chart.jsx rename to packages/trader/src/App/Containers/SettingsModal/settings-chart.tsx index 255fb5e7205d..ff588813cdf9 100644 --- a/packages/trader/src/App/Containers/SettingsModal/settings-chart.jsx +++ b/packages/trader/src/App/Containers/SettingsModal/settings-chart.tsx @@ -42,7 +42,9 @@ const ChartSettings = observer(() => { defaultChecked={is_countdown_visible} label={localize('Display remaining time for each interval')} onChange={e => { - setCountdown(e.target.checked); + if ('checked' in e.target) { + setCountdown(e.target.checked); + } }} /> diff --git a/packages/trader/src/App/Containers/SettingsModal/settings-purchase.jsx b/packages/trader/src/App/Containers/SettingsModal/settings-purchase.jsx deleted file mode 100644 index 4bbf1e2d5ab1..000000000000 --- a/packages/trader/src/App/Containers/SettingsModal/settings-purchase.jsx +++ /dev/null @@ -1,85 +0,0 @@ -// import { Checkbox } from '@deriv/components'; -// import PropTypes from 'prop-types'; -// import React from 'react'; -// import { localize } from '@deriv/translations'; -// import MediaItem, { -// MediaDescription, -// MediaHeading, -// MediaIcon, -// } from 'App/Components/Elements/Media'; -// import ConfirmationDisabledLightIcon from 'Assets/SvgComponents/settings/confirmation-disabled.svg'; -// import ConfirmationEnabledLightIcon from 'Assets/SvgComponents/settings/confirmation-enabled.svg'; -// import ConfirmationDisabledDarkIcon from 'Assets/SvgComponents/settings/dark/confirmation-disabled.svg'; -// import ConfirmationEnabledDarkIcon from 'Assets/SvgComponents/settings/dark/confirmation-enabled.svg'; -// import LockDisabledDarkIcon from 'Assets/SvgComponents/settings/dark/lock-disabled.svg'; -// import LockEnabledDarkIcon from 'Assets/SvgComponents/settings/dark/lock-enabled.svg'; -// import LockDisabledLightIcon from 'Assets/SvgComponents/settings/lock-disabled.svg'; -// import LockEnabledLightIcon from 'Assets/SvgComponents/settings/lock-enabled.svg'; -// import { connect } from 'Stores/connect'; -// -// const PurchaseSettings = ({ -// is_dark_mode, -// is_purchase_confirmed, -// is_purchase_locked, -// setPurchaseLock, -// togglePurchaseConfirmation, -// }) => ( -//
-// -// -// -// -// -// -//
-// -//
-//
-//
-// -// -// -// -// -// -//
-// { setPurchaseLock(e.target.checked); }} -// /> -//
-//
-//
-//
-// ); -// -// PurchaseSettings.propTypes = { -// is_dark_mode : PropTypes.bool, -// is_purchase_confirmed : PropTypes.bool, -// is_purchase_locked : PropTypes.bool, -// togglePurchaseConfirmation: PropTypes.func, -// togglePurchaseLock : PropTypes.func, -// }; -// -// export default connect(({ ui }) => ( -// { -// is_dark_mode : ui.is_dark_mode_on, -// is_purchase_confirmed : ui.is_purchase_confirm_on, -// is_purchase_locked : ui.is_purchase_lock_on, -// togglePurchaseConfirmation: ui.togglePurchaseConfirmation, -// setPurchaseLock : ui.setPurchaseLock, -// } -// ))(PurchaseSettings); diff --git a/packages/trader/src/App/Containers/trade-settings-extensions.tsx b/packages/trader/src/App/Containers/trade-settings-extensions.tsx index 6fbe4cf4b4f7..ccf1a2914a1a 100644 --- a/packages/trader/src/App/Containers/trade-settings-extensions.tsx +++ b/packages/trader/src/App/Containers/trade-settings-extensions.tsx @@ -13,17 +13,11 @@ type TTradeSettingsExtensionsProps = { const ChartSettingContainer = Loadable({ loader: () => import( - /* webpackChunkName: "settings-chart", webpackPrefetch: true */ 'App/Containers/SettingsModal/settings-chart.jsx' + /* webpackChunkName: "settings-chart", webpackPrefetch: true */ 'App/Containers/SettingsModal/settings-chart' ), loading: () => , }); -// const PurchaseSettings = Loadable({ -// loader: () => -// import(/* webpackChunkName: "settings-chart", webpackPrefetch: true */'App/Containers/SettingsModal/settings-purchase.jsx'), -// loading: UILoader, -// }); - const renderItemValue = (props: T, store: TCoreStores) => ( @@ -39,11 +33,6 @@ const TradeSettingsExtensions = observer(({ store }: TTradeSettingsExtensionsPro icon: 'IcChart', label: localize('Charts'), value: props => renderItemValue(props, store), - // uncomment below lines to bring back purchase lock and purchase confirmation} - // }, { - // icon : IconPurchase, - // label: localize('Purchase'), - // value: PurchaseSettings, }, ]; populateSettingsExtensions(menu_items); diff --git a/packages/trader/src/App/app.tsx b/packages/trader/src/App/app.tsx index bbafd8fa512f..faf20885c37d 100644 --- a/packages/trader/src/App/app.tsx +++ b/packages/trader/src/App/app.tsx @@ -1,6 +1,6 @@ import React from 'react'; import Loadable from 'react-loadable'; -import Routes from 'App/Containers/Routes/routes.jsx'; +import Routes from 'App/Containers/Routes/routes'; import TradeHeaderExtensions from 'App/Containers/trade-header-extensions'; import TradeFooterExtensions from 'App/Containers/trade-footer-extensions'; import TradeSettingsExtensions from 'App/Containers/trade-settings-extensions'; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/asian-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/asian-trade-description.spec.tsx new file mode 100644 index 000000000000..d3c001ac0e8f --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/asian-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import AsianTradeDescription from '../asian-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/Asian options settle by comparing/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/call-put-spread-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/call-put-spread-trade-description.spec.tsx new file mode 100644 index 000000000000..115d64d830e0 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/call-put-spread-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import CallPutSpreadTradeDescription from '../call-put-spread-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/Win maximum payout if the exit spot is higher/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/end-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/end-trade-description.spec.tsx new file mode 100644 index 000000000000..c104601c8f0a --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/end-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import EndTradeDescription from '../end-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Ends Between", you win the payout/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/even-odd-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/even-odd-trade-description.spec.tsx new file mode 100644 index 000000000000..173c95fd0e13 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/even-odd-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import EvenOddTradeDescription from '../even-odd-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Even", you will win the payout/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/high-low-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/high-low-trade-description.spec.tsx new file mode 100644 index 000000000000..318e17052042 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/high-low-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import HighLowTradeDescription from '../high-low-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Higher", you win the payout/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/lb-call-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/lb-call-trade-description.spec.tsx new file mode 100644 index 000000000000..6ec7fee31e9b --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/lb-call-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import LbCallTradeDescription from '../lb-call-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/By purchasing the "Close-to-Low" contract/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/lb-high-low-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/lb-high-low-trade-description.spec.tsx new file mode 100644 index 000000000000..567564c6d342 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/lb-high-low-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import LbHighLowTradeDescription from '../lb-high-low-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/By purchasing the "High-to-Low" contract, you/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/lb-put-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/lb-put-trade-description.spec.tsx new file mode 100644 index 000000000000..dd4ec8d5bf53 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/lb-put-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import LbPutTradeDescription from '../lb-put-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/By purchasing the "High-to-Close" contract/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/match-diff-trade-descriptioon.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/match-diff-trade-descriptioon.spec.tsx new file mode 100644 index 000000000000..77d2d30edb35 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/match-diff-trade-descriptioon.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import MatchDiffTradeDescription from '../match-diff-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Matches", you will win the payout/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/over-under-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/over-under-trade-description.spec.tsx new file mode 100644 index 000000000000..18946af8dee6 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/over-under-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import OverUnderTradeDescription from '../over-under-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Over", you will win the payout/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/reset-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/reset-trade-description.spec.tsx new file mode 100644 index 000000000000..a25e4ba3878b --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/reset-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import ResetTradeDescription from '../reset-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Reset-Up”, you win the payout/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/rise-fall-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/rise-fall-trade-description.spec.tsx new file mode 100644 index 000000000000..e1dcb15c49b5 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/rise-fall-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import RiseFallTradeDescription from '../rise-fall-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Rise", you win the payout if the exit/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/run-high-low-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/run-high-low-trade-description.spec.tsx new file mode 100644 index 000000000000..56b3303cc89a --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/run-high-low-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import RunHighLowTradeDescription from '../run-high-low-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Only Ups", you win the payout if consecutive/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/stay-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/stay-trade-description.spec.tsx new file mode 100644 index 000000000000..0aa99cfc1252 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/stay-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import StayTradeDescription from '../stay-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Stays Between", you win the payout/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/tick-high-low-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/tick-high-low-trade-description.spec.tsx new file mode 100644 index 000000000000..fcba0774b535 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/tick-high-low-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import TickHighLowTradeDescription from '../tick-high-low-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "High Tick", you win the payout/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/touch-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/touch-trade-description.spec.tsx new file mode 100644 index 000000000000..6fd49ca7b520 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/touch-trade-description.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import TouchTradeDescription from '../touch-trade-description'; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/If you select "Touch", you win the payout/i)).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/turbos-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/turbos-trade-description.spec.tsx index b6f9e49d7ffe..b025c0c31460 100644 --- a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/turbos-trade-description.spec.tsx +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/turbos-trade-description.spec.tsx @@ -5,6 +5,7 @@ import TurbosTradeDescription from '../turbos-trade-description'; describe('', () => { it('a proper text of description should be rendered', () => { render(); + expect( screen.getByText(/Turbo options allow you to predict the direction of the underlying asset’s movements./i) ).toBeInTheDocument(); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/__tests__/vanilla-trade-description.spec.tsx b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/vanilla-trade-description.spec.tsx new file mode 100644 index 000000000000..9b602403d9db --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/__tests__/vanilla-trade-description.spec.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import VanillaTradeDescription from '../vanilla-trade-description'; + +const mocked_props = { + onClick: jest.fn(), +}; + +describe('', () => { + it('a proper text of description should be rendered', () => { + render(); + + expect(screen.getByText(/Vanilla options allow you to predict/i)).toBeInTheDocument(); + }); + + it('specific text of description should be rendered if is_vanilla_fx is true', () => { + render(); + + expect(screen.getByText(/payout per pip/i)).toBeInTheDocument(); + expect(screen.getByText(/You may sell the contract up to 24 hours before expiry/i)).toBeInTheDocument(); + }); + + it('should call a function if word from vocabulary was clicked', () => { + render(); + + const glossary_word = screen.getByText(/payout per point/i); + userEvent.click(glossary_word); + + expect(mocked_props.onClick).toBeCalled(); + }); +}); diff --git a/packages/trader/src/Assets/Trading/Categories/Description/accumulator-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/accumulator-trade-description.tsx index e9ee35cbc4cb..c0f81a24e013 100644 --- a/packages/trader/src/Assets/Trading/Categories/Description/accumulator-trade-description.tsx +++ b/packages/trader/src/Assets/Trading/Categories/Description/accumulator-trade-description.tsx @@ -2,37 +2,36 @@ import React from 'react'; import { Localize } from '@deriv/translations'; import { Text } from '@deriv/components'; -const AccumulatorTradeDescription = ({ onClick }: { onClick: () => void }) => { +const AccumulatorTradeDescription = ({ onClick }: { onClick: React.MouseEventHandler }) => { + const content = [ + ]} + key='1' + />, + ]} + key='2' + />, + ]} + key='3' + />, + ]} + key='4' + />, + ]; return ( - - growth rate.' - } - components={[]} - /> - - - payout is the sum of your inital stake and profit.'} - components={[]} - /> - - - range from the <0>previous spot price. Otherwise, you lose your stake and the trade is terminated.' - } - components={[]} - /> - - - slippage risk.'} - components={[]} - /> - + {content.map(paragraph => ( + + {paragraph} + + ))} ); }; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/asian-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/asian-trade-description.tsx new file mode 100644 index 000000000000..fc1ab187b253 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/asian-trade-description.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const AsianTradeDescription = () => { + const content = [ + , + , + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default AsianTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/call-put-spread-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/call-put-spread-trade-description.tsx new file mode 100644 index 000000000000..ba18e76a4665 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/call-put-spread-trade-description.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const CallPutSpreadTradeDescription = () => { + const content = [ + { type: 'heading', text: }, + { + type: 'paragraph', + text: ( + + ), + }, + { + type: 'paragraph', + text: ( + + ), + }, + { + type: 'paragraph', + text: , + }, + { type: 'heading', text: }, + { + type: 'paragraph', + text: ( + + ), + }, + { + type: 'paragraph', + text: ( + + ), + }, + { + type: 'paragraph', + text: , + }, + ]; + + return ( + + {content.map(({ type, text }) => + type === 'heading' ? ( + + {text} + + ) : ( + + {text} + + ) + )} + + ); +}; + +export default CallPutSpreadTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/end-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/end-trade-description.tsx new file mode 100644 index 000000000000..4ea612c9c207 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/end-trade-description.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const EndTradeDescription = () => { + const content = [ + , + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default EndTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/even-odd-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/even-odd-trade-description.tsx new file mode 100644 index 000000000000..48c1adc99169 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/even-odd-trade-description.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const EvenOddTradeDescription = () => { + const content = [ + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default EvenOddTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/high-low-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/high-low-trade-description.tsx new file mode 100644 index 000000000000..090bb593f711 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/high-low-trade-description.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const HighLowTradeDescription = () => { + const content = [ + , + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default HighLowTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/lb-call-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/lb-call-trade-description.tsx new file mode 100644 index 000000000000..aa188fba9dda --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/lb-call-trade-description.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const LbCallTradeDescription = () => { + const content = [ + , + , + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default LbCallTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/lb-high-low-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/lb-high-low-trade-description.tsx new file mode 100644 index 000000000000..8f6c00ec11a8 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/lb-high-low-trade-description.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const LbHighLowTradeDescription = () => { + const content = [ + , + , + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default LbHighLowTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/lb-put-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/lb-put-trade-description.tsx new file mode 100644 index 000000000000..d2bd3c11b971 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/lb-put-trade-description.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const LbPutTradeDescription = () => { + const content = [ + , + , + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default LbPutTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/match-diff-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/match-diff-trade-description.tsx new file mode 100644 index 000000000000..cf7dbe9882be --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/match-diff-trade-description.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const MatchDiffTradeDescription = () => { + const content = [ + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default MatchDiffTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/over-under-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/over-under-trade-description.tsx new file mode 100644 index 000000000000..9638c6457343 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/over-under-trade-description.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const OverUnderTradeDescription = () => { + const content = [ + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default OverUnderTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/reset-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/reset-trade-description.tsx new file mode 100644 index 000000000000..171bfadeebc3 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/reset-trade-description.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const ResetTradeDescription = () => { + const content = [ + , + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default ResetTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/rise-fall-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/rise-fall-trade-description.tsx new file mode 100644 index 000000000000..524063f1f649 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/rise-fall-trade-description.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const RiseFallTradeDescription = () => { + const content = [ + , + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default RiseFallTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/run-high-low-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/run-high-low-trade-description.tsx new file mode 100644 index 000000000000..e958da0fcb7d --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/run-high-low-trade-description.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const RunHighLowTradeDescription = () => { + const content = [ + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default RunHighLowTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/stay-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/stay-trade-description.tsx new file mode 100644 index 000000000000..1593efe2db1f --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/stay-trade-description.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const StayTradeDescription = () => { + const content = [ + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default StayTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/tick-high-low-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/tick-high-low-trade-description.tsx new file mode 100644 index 000000000000..3c42dabfbde3 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/tick-high-low-trade-description.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const TickHighLowTradeDescription = () => { + const content = [ + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default TickHighLowTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/touch-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/touch-trade-description.tsx new file mode 100644 index 000000000000..c2b3c44114dc --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/touch-trade-description.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const TouchTradeDescription = () => { + const content = [ + , + , + ]; + return ( + + {content.map(paragraph => ( + + {paragraph} + + ))} + + ); +}; + +export default TouchTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/Description/turbos-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/turbos-trade-description.tsx index b7a0ef40a7f1..a2e9f79fe5fe 100644 --- a/packages/trader/src/Assets/Trading/Categories/Description/turbos-trade-description.tsx +++ b/packages/trader/src/Assets/Trading/Categories/Description/turbos-trade-description.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Localize } from '@deriv/translations'; import { Text } from '@deriv/components'; -const TurbosTradeDescription = ({ onClick }: { onClick: () => void }) => { +const TurbosTradeDescription = ({ onClick }: { onClick: React.MouseEventHandler }) => { const content = [ { text: ( diff --git a/packages/trader/src/Assets/Trading/Categories/Description/vanilla-trade-description.tsx b/packages/trader/src/Assets/Trading/Categories/Description/vanilla-trade-description.tsx new file mode 100644 index 000000000000..78510fdf21f9 --- /dev/null +++ b/packages/trader/src/Assets/Trading/Categories/Description/vanilla-trade-description.tsx @@ -0,0 +1,81 @@ +import React from 'react'; +import { Localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +const VanillaTradeDescription = ({ + is_vanilla_fx, + onClick, +}: { + is_vanilla_fx?: boolean; + onClick: React.MouseEventHandler; +}) => { + const content = [ + , + , + , + ]} + key='2' + />, + ]} + key='3' + />, + { + content: is_vanilla_fx ? ( + , + , + ]} + key='4' + /> + ) : ( + ]} + key='4' + /> + ), + }, + { + content: is_vanilla_fx ? ( + ]} + key='5' + /> + ) : ( + ]} + key='5' + /> + ), + }, + ] as Array; + return ( + + {content.map(paragraph => { + const key = paragraph.props + ? paragraph.props.i18n_default_text + : paragraph.content?.props.i18n_default_text; + const text = paragraph.content ?? paragraph; + return ( + + {text} + + ); + })} + + ); +}; + +export default VanillaTradeDescription; diff --git a/packages/trader/src/Assets/Trading/Categories/__tests__/contract-type-description-video.spec.tsx b/packages/trader/src/Assets/Trading/Categories/__tests__/contract-type-description-video.spec.tsx index 7e0d00ecc520..23b9cf867185 100644 --- a/packages/trader/src/Assets/Trading/Categories/__tests__/contract-type-description-video.spec.tsx +++ b/packages/trader/src/Assets/Trading/Categories/__tests__/contract-type-description-video.spec.tsx @@ -22,18 +22,25 @@ describe('', () => { ); }; it('should render the component with video if selected_contract_type does support video', () => { - const mock_root_store = mockStore({}); - render(mockContractTypeDescriptionVideo(mock_root_store, default_mocked_props)); - const video = screen.getByTestId(/description_video/i); + render(mockContractTypeDescriptionVideo(mockStore({}), default_mocked_props)); - expect(video).toBeInTheDocument(); + expect(screen.getByTestId(/description_video/i)).toBeInTheDocument(); }); + it('should be able to find a proper video and render the component if is_dark_mode_on is true', () => { const mock_root_store = mockStore({ ui: { is_dark_mode_on: true } }); render(mockContractTypeDescriptionVideo(mock_root_store, default_mocked_props)); expect(screen.getByTestId(/description_video/i)).toBeInTheDocument(); }); + + it('should return null if selected_contract_type is falsy', () => { + const new_mocked_props = { ...default_mocked_props, selected_contract_type: '' }; + const { container } = render(mockContractTypeDescriptionVideo(mockStore({}), new_mocked_props)); + + expect(container).toBeEmptyDOMElement(); + }); + it('should render the component with video of proper width and height if it is mobile', () => { const mock_root_store = mockStore({ ui: { is_mobile: true } }); render(mockContractTypeDescriptionVideo(mock_root_store, default_mocked_props)); diff --git a/packages/trader/src/Assets/Trading/Categories/__tests__/icon-trade-categories.spec.tsx b/packages/trader/src/Assets/Trading/Categories/__tests__/icon-trade-categories.spec.tsx index 178b625d6e5e..93f6029247ce 100644 --- a/packages/trader/src/Assets/Trading/Categories/__tests__/icon-trade-categories.spec.tsx +++ b/packages/trader/src/Assets/Trading/Categories/__tests__/icon-trade-categories.spec.tsx @@ -184,6 +184,15 @@ describe('', () => { expect(icon).toHaveClass('category-wrapper'); }); }); + it('Expect two MockedIcons to be rendered when category is turboslong', () => { + render(); + const mocked_icons = screen.getAllByText(mocked_icon); + expect(mocked_icons).toHaveLength(2); + mocked_icons.forEach(icon => { + expect(icon).toBeInTheDocument(); + expect(icon).toHaveClass('category-wrapper'); + }); + }); it('Expect default case to be rendered when category is not valid', () => { render(); const mocked_icon_text = screen.getByText(mocked_icon); diff --git a/packages/trader/src/Assets/Trading/Categories/__tests__/trade-categories-gif.spec.tsx b/packages/trader/src/Assets/Trading/Categories/__tests__/trade-categories-gif.spec.tsx index 8bc6a7f4c71f..614294f7c5bd 100644 --- a/packages/trader/src/Assets/Trading/Categories/__tests__/trade-categories-gif.spec.tsx +++ b/packages/trader/src/Assets/Trading/Categories/__tests__/trade-categories-gif.spec.tsx @@ -260,7 +260,7 @@ describe('', () => { }); }); }); - it('expect ImageAccumulator to be rendered when trade category is accumulator', async () => { + it('expect VideoAccumulator to be rendered when trade category is accumulator', async () => { jest.isolateModules(() => { jest.doMock('../contract-type-description-video', () => ({ __esModule: true, @@ -328,10 +328,41 @@ describe('', () => { }); }); }); - it('component should return null if category is not defined correctly', async () => { + it('expect ImageTurbos to be rendered when trade category is turboslong', async () => { + jest.isolateModules(() => { + jest.doMock('Assets/SvgComponents/trade_explanations/turboslong.svg', () => ({ + __esModule: true, + default: jest.fn(() => 'ImageTurbos'), + })); + + import('../trade-categories-gif') + .then(moduleName => { + render(); + expect(screen.getByText(/imageturbos/i)).toBeInTheDocument(); + }) + .catch(error => { + throw new Error(error); + }); + }); + }); + it('component should return null if category is not equal to selected_contract_type', async () => { + import('../trade-categories-gif') + .then(moduleName => { + const { container } = render( + + ); + expect(container).toBeEmptyDOMElement(); + }) + .catch(error => { + throw new Error(error); + }); + }); + it('component should return null if category and selected_contract_type are not defined correctly', async () => { import('../trade-categories-gif') .then(moduleName => { - const { container } = render(); + const { container } = render( + + ); expect(container).toBeEmptyDOMElement(); }) .catch(error => { diff --git a/packages/trader/src/Assets/Trading/Categories/__tests__/trade-categories.spec.tsx b/packages/trader/src/Assets/Trading/Categories/__tests__/trade-categories.spec.tsx index b2fbecda8d6c..6b8960616f96 100644 --- a/packages/trader/src/Assets/Trading/Categories/__tests__/trade-categories.spec.tsx +++ b/packages/trader/src/Assets/Trading/Categories/__tests__/trade-categories.spec.tsx @@ -3,159 +3,108 @@ import { render, screen } from '@testing-library/react'; import TradeCategories from '../trade-categories'; jest.mock('../Description/accumulator-trade-description', () => jest.fn(() => 'mockedAccumulatorTradeDescription')); -jest.mock('../Description/turbos-trade-description', () => jest.fn(() => 'mockedTurbosTradeDescription')); +jest.mock('../Description/asian-trade-description', () => jest.fn(() => 'mockedAsianTradeDescription')); +jest.mock('../Description/call-put-spread-trade-description', () => + jest.fn(() => 'mockedCallPutSpreadTradeDescription') +); +jest.mock('../Description/end-trade-description', () => jest.fn(() => 'mockedEndTradeDescription')); +jest.mock('../Description/even-odd-trade-description', () => jest.fn(() => 'mockedEvenOddTradeDescription')); +jest.mock('../Description/high-low-trade-description', () => jest.fn(() => 'mockedHighLowTradeDescription')); +jest.mock('../Description/lb-call-trade-description', () => jest.fn(() => 'mockedLbCallTradeDescription')); +jest.mock('../Description/lb-high-low-trade-description', () => jest.fn(() => 'mockedLbHighLowTradeDescription')); +jest.mock('../Description/lb-put-trade-description', () => jest.fn(() => 'mockedLbPutTradeDescription')); +jest.mock('../Description/match-diff-trade-description', () => jest.fn(() => 'mockedMatchDiffTradeDescription')); jest.mock('../Description/multiplier-trade-description', () => jest.fn(() => 'mockedMultiplierTradeDescription')); +jest.mock('../Description/over-under-trade-description', () => jest.fn(() => 'mockedOverUnderTradeDescription')); +jest.mock('../Description/reset-trade-description', () => jest.fn(() => 'mockedResetTradeDescription')); +jest.mock('../Description/rise-fall-trade-description', () => jest.fn(() => 'mockedRiseFallTradeDescription')); +jest.mock('../Description/run-high-low-trade-description', () => jest.fn(() => 'mockedRunHighLowTradeDescription')); +jest.mock('../Description/stay-trade-description', () => jest.fn(() => 'mockedStayTradeDescription')); +jest.mock('../Description/tick-high-low-trade-description', () => jest.fn(() => 'mockedTickHighLowTradeDescription')); +jest.mock('../Description/touch-trade-description', () => jest.fn(() => 'mockedTouchTradeDescription')); +jest.mock('../Description/turbos-trade-description', () => jest.fn(() => 'mockedTurbosTradeDescription')); +jest.mock('../Description/vanilla-trade-description', () => jest.fn(() => 'mockedVanillaTradeDescription')); -describe('', () => { - it('Ensure mockedAccumulatorTradeDescription is rendered correctly when trade category is "accumulator"', () => { +describe('', () => { + it('Ensure AccumulatorTradeDescription is rendered correctly when trade category is "accumulator"', () => { render(); expect(screen.getByText(/mockedaccumulatortradedescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "rise_fall" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /If you select "Rise", you win the payout if the exit spot is strictly higher than the entry spot./i - ) - ).toBeInTheDocument(); - }); - it('Ensure trade category "rise_fall_equal" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /If you select "Allow equals", you win the payout if exit spot is higher than or equal to entry spot for "Rise". Similarly, you win the payout if exit spot is lower than or equal to entry spot for "Fall"./i - ) - ).toBeInTheDocument(); - }); - it('Ensure trade category "high_low" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /If you select "Higher", you win the payout if the exit spot is strictly higher than the barrier./i - ) - ).toBeInTheDocument(); + it('Ensure mockedAsianTradeDescription is rendered correctly when trade category is "asian"', () => { + render(); + expect(screen.getByText(/mockedAsianTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "end" description is rendered properly', () => { + it('Ensure mockedCallPutSpreadTradeDescription is rendered correctly when trade category is "callputspread"', () => { + render(); + expect(screen.getByText(/mockedCallPutSpreadTradeDescription/i)).toBeInTheDocument(); + }); + it('Ensure mockedEndTradeDescription is rendered correctly when trade category is "end"', () => { render(); - expect( - screen.getByText( - /If you select "Ends Between", you win the payout if the exit spot is strictly higher than the Low barrier AND strictly lower than the High barrier./i - ) - ).toBeInTheDocument(); + expect(screen.getByText(/mockedEndTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "stay" description is rendered properly', () => { - render(); - expect( - screen.getByText(/If you select "Stays Between", you win the payout if the market stays between/i) - ).toBeInTheDocument(); + it('Ensure mockedEvenOddTradeDescription is rendered correctly when trade category is "even_odd"', () => { + render(); + expect(screen.getByText(/mockedEvenOddTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "match_diff" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /If you select "Matches", you will win the payout if the last digit of the last tick is the same as your prediction./i - ) - ).toBeInTheDocument(); + it('Ensure mockedHighLowTradeDescription is rendered correctly when trade category is "high_low"', () => { + render(); + expect(screen.getByText(/mockedHighLowTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "even_odd" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /If you select "Even", you will win the payout if the last digit of the last tick is an even number/i - ) - ).toBeInTheDocument(); + it('Ensure mockedLbCallTradeDescription is rendered correctly when trade category is "lb_call"', () => { + render(); + expect(screen.getByText(/mockedLbCallTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "over_under" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /If you select "Over", you will win the payout if the last digit of the last tick is greater than your prediction./i - ) - ).toBeInTheDocument(); + it('Ensure mockedLbHighLowTradeDescription is rendered correctly when trade category is "lb_high_low"', () => { + render(); + expect(screen.getByText(/mockedLbHighLowTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "touch" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /If you select "Touch", you win the payout if the market touches the barrier at any time during the contract period./i - ) - ).toBeInTheDocument(); + it('Ensure mockedLbPutTradeDescription is rendered correctly when trade category is "lb_put"', () => { + render(); + expect(screen.getByText(/mockedLbPutTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "asian" description is rendered properly', () => { - render(); - expect( - screen.getByText(/Asian options settle by comparing the last tick with the average spot over the period./i) - ).toBeInTheDocument(); + it('Ensure mockedMatchDiffTradeDescription is rendered correctly when trade category is "match_diff"', () => { + render(); + expect(screen.getByText(/mockedMatchDiffTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "run_high_low" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /If you select "Only Ups", you win the payout if consecutive ticks rise successively after the entry spot. No payout if any tick falls or is equal to any of the previous ticks./i - ) - ).toBeInTheDocument(); + it('Ensure mockedMultiplierTradeDescription is rendered correctly when trade category is "multiplier"', () => { + render(); + expect(screen.getByText(/mockedMultiplierTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "reset" description is rendered properly', () => { + it('Ensure mockedOverUnderTradeDescription is rendered correctly when trade category is "over_under"', () => { + render(); + expect(screen.getByText(/mockedOverUnderTradeDescription/i)).toBeInTheDocument(); + }); + it('Ensure mockedResetTradeDescription is rendered correctly when trade category is "reset"', () => { render(); - expect( - screen.getByText( - /If you select "Reset-Up”, you win the payout if the exit spot is strictly higher than either the entry spot or the spot at reset time./i - ) - ).toBeInTheDocument(); + expect(screen.getByText(/mockedResetTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "callputspread" description is rendered properly', () => { - render(); - expect( - screen.getByText(/Win maximum payout if the exit spot is higher than or equal to the upper barrier./i) - ).toBeInTheDocument(); + it('Ensure mockedRiseFallTradeDescription is rendered correctly when trade category is "rise_fall"', () => { + render(); + expect(screen.getByText(/mockedRiseFallTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "tick_high_low" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /If you select "High Tick", you win the payout if the selected tick is the highest among the next five ticks./i - ) - ).toBeInTheDocument(); + it('Ensure mockedRunHighLowTradeDescription is rendered correctly when trade category is "run_high_low"', () => { + render(); + expect(screen.getByText(/mockedRunHighLowTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "lb_high_low" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /By purchasing the "High-to-Low" contract, you'll win the multiplier times the difference between the high and low over the duration of the contract./i - ) - ).toBeInTheDocument(); + it('Ensure mockedStayTradeDescription is rendered correctly when trade category is "stay"', () => { + render(); + expect(screen.getByText(/mockedStayTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "lb_put" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /By purchasing the "High-to-Close" contract, you'll win the multiplier times the difference between the high and close over the duration of the contract./i - ) - ).toBeInTheDocument(); + it('Ensure mockedTickHighLowTradeDescription is rendered correctly when trade category is "tick_high_low"', () => { + render(); + expect(screen.getByText(/mockedTickHighLowTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "lb_call" description is rendered properly', () => { - render(); - expect( - screen.getByText( - /By purchasing the "Close-to-Low" contract, you'll win the multiplier times the difference between the close and low over the duration of the contract./i - ) - ).toBeInTheDocument(); - }); - it('Ensure trade category "multiplier" description is rendered properly', () => { - render(); - expect(screen.getByText(/mockedMultiplierTradeDescription/i)).toBeInTheDocument(); + it('Ensure mockedTouchTradeDescription is rendered correctly when trade category is "touch"', () => { + render(); + expect(screen.getByText(/mockedTouchTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "turbosshort" description is rendered properly', () => { + it('Ensure mockedTurbosTradeDescription is rendered correctly when trade category is "turbosshort"', () => { render(); expect(screen.getByText(/mockedTurbosTradeDescription/i)).toBeInTheDocument(); }); - it('Ensure trade category "vanillalongcall" description is rendered properly', () => { + it('Ensure mockedVanillaTradeDescription is rendered correctly when trade category is "vanillalongcall"', () => { render(); - expect( - screen.getByText( - 'Vanilla options allow you to predict an upward (bullish) or downward (bearish) direction of the underlying asset by purchasing a "Call" or a "Put".' - ) - ).toBeInTheDocument(); + expect(screen.getByText(/mockedVanillaTradeDescription/i)).toBeInTheDocument(); }); it('Ensure description is not found is rendered when trade category doesnt exist', () => { render(); diff --git a/packages/trader/src/Assets/Trading/Categories/trade-categories.tsx b/packages/trader/src/Assets/Trading/Categories/trade-categories.tsx index 0aea9cb29f39..abfcaf944c6b 100644 --- a/packages/trader/src/Assets/Trading/Categories/trade-categories.tsx +++ b/packages/trader/src/Assets/Trading/Categories/trade-categories.tsx @@ -1,13 +1,28 @@ import React from 'react'; import { Text } from '@deriv/components'; import { VANILLALONG, TURBOS } from '@deriv/shared'; -import { localize, Localize } from '@deriv/translations'; +import { Localize } from '@deriv/translations'; import AccumulatorTradeDescription from './Description/accumulator-trade-description'; -import TurbosTradeDescription from './Description/turbos-trade-description'; +import AsianTradeDescription from './Description/asian-trade-description'; +import CallPutSpreadTradeDescription from './Description/call-put-spread-trade-description'; +import EndTradeDescription from './Description/end-trade-description'; +import EvenOddTradeDescription from './Description/even-odd-trade-description'; +import HighLowTradeDescription from './Description/high-low-trade-description'; +import LbHighLowTradeDescription from './Description/lb-high-low-trade-description'; +import LbPutTradeDescription from './Description/lb-put-trade-description'; +import LbCallTradeDescription from './Description/lb-call-trade-description'; +import MatchDiffTradeDescription from './Description/match-diff-trade-description'; import MultiplierTradeDescription from './Description/multiplier-trade-description'; +import OverUnderTradeDescription from './Description/over-under-trade-description'; +import RiseFallTradeDescription from './Description/rise-fall-trade-description'; +import RunHighLowTradeDescription from './Description/run-high-low-trade-description'; +import ResetTradeDescription from './Description/reset-trade-description'; +import StayTradeDescription from './Description/stay-trade-description'; +import TurbosTradeDescription from './Description/turbos-trade-description'; +import TouchTradeDescription from './Description/touch-trade-description'; +import TickHighLowTradeDescription from './Description/tick-high-low-trade-description'; +import VanillaTradeDescription from './Description/vanilla-trade-description'; -// Templates are from Binary 1.0, it should be checked if they need change or not and add all of trade types -// TODO: refactor the rest of descriptions to use them as components like AccumulatorTradeDescription const TradeCategories = ({ category, onClick, @@ -15,7 +30,7 @@ const TradeCategories = ({ is_multiplier_fx = false, }: { category?: string; - onClick: () => void; + onClick: React.MouseEventHandler; is_vanilla_fx?: boolean; is_multiplier_fx?: boolean; }) => { @@ -26,353 +41,53 @@ const TradeCategories = ({ TradeTypeTemplate = ; break; case 'rise_fall': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Rise", you win the payout if the exit spot is strictly higher than the entry spot.' - )} - - - {localize( - 'If you select "Fall", you win the payout if the exit spot is strictly lower than the entry spot.' - )} - - - {localize( - 'If you select "Allow equals", you win the payout if exit spot is higher than or equal to entry spot for "Rise". Similarly, you win the payout if exit spot is lower than or equal to entry spot for "Fall".' - )} - - - ); - break; case 'rise_fall_equal': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Rise", you win the payout if the exit spot is strictly higher than the entry spot.' - )} - - - {localize( - 'If you select "Fall", you win the payout if the exit spot is strictly lower than the entry spot.' - )} - - - {localize( - 'If you select "Allow equals", you win the payout if exit spot is higher than or equal to entry spot for "Rise". Similarly, you win the payout if exit spot is lower than or equal to entry spot for "Fall".' - )} - - - ); + TradeTypeTemplate = ; break; case 'high_low': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Higher", you win the payout if the exit spot is strictly higher than the barrier.' - )} - - - {localize( - 'If you select "Lower", you win the payout if the exit spot is strictly lower than the barrier.' - )} - - - {localize("If the exit spot is equal to the barrier, you don't win the payout.")} - - - ); + TradeTypeTemplate = ; break; case 'end': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Ends Between", you win the payout if the exit spot is strictly higher than the Low barrier AND strictly lower than the High barrier.' - )} - - - {localize( - 'If you select "Ends Outside", you win the payout if the exit spot is EITHER strictly higher than the High barrier, OR strictly lower than the Low barrier.' - )} - - - {localize( - "If the exit spot is equal to either the Low barrier or the High barrier, you don't win the payout." - )} - - - ); + TradeTypeTemplate = ; break; case 'stay': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Stays Between", you win the payout if the market stays between (does not touch) either the High barrier or the Low barrier at any time during the contract period' - )} - - - {localize( - 'If you select "Goes Outside", you win the payout if the market touches either the High barrier or the Low barrier at any time during the contract period.' - )} - - - ); + TradeTypeTemplate = ; break; case 'match_diff': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Matches", you will win the payout if the last digit of the last tick is the same as your prediction.' - )} - - - {localize( - 'If you select "Differs", you will win the payout if the last digit of the last tick is not the same as your prediction.' - )} - - - ); + TradeTypeTemplate = ; break; case 'even_odd': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Even", you will win the payout if the last digit of the last tick is an even number (i.e., 2, 4, 6, 8, or 0).' - )} - - - {localize( - 'If you select "Odd", you will win the payout if the last digit of the last tick is an odd number (i.e., 1, 3, 5, 7, or 9).' - )} - - - ); + TradeTypeTemplate = ; break; case 'over_under': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Over", you will win the payout if the last digit of the last tick is greater than your prediction.' - )} - - - {localize( - 'If you select "Under", you will win the payout if the last digit of the last tick is less than your prediction.' - )} - - - ); + TradeTypeTemplate = ; break; case 'touch': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Touch", you win the payout if the market touches the barrier at any time during the contract period.' - )} - - - {localize( - 'If you select "No Touch", you win the payout if the market never touches the barrier at any time during the contract period.' - )} - - - ); + TradeTypeTemplate = ; break; case 'asian': - TradeTypeTemplate = ( - - - {localize( - 'Asian options settle by comparing the last tick with the average spot over the period.' - )} - - - {localize( - 'If you select "Asian Rise", you will win the payout if the last tick is higher than the average of the ticks.' - )} - - - {localize( - 'If you select "Asian Fall", you will win the payout if the last tick is lower than the average of the ticks.' - )} - - - {localize( - "If the last tick is equal to the average of the ticks, you don't win the payout." - )} - - - ); + TradeTypeTemplate = ; break; case 'run_high_low': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Only Ups", you win the payout if consecutive ticks rise successively after the entry spot. No payout if any tick falls or is equal to any of the previous ticks.' - )} - - - {localize( - 'If you select "Only Downs", you win the payout if consecutive ticks fall successively after the entry spot. No payout if any tick rises or is equal to any of the previous ticks.' - )} - - - ); + TradeTypeTemplate = ; break; case 'reset': - TradeTypeTemplate = ( - - - {localize( - 'If you select "Reset-Up”, you win the payout if the exit spot is strictly higher than either the entry spot or the spot at reset time.' - )} - - - {localize( - 'If you select "Reset-Down”, you win the payout if the exit spot is strictly lower than either the entry spot or the spot at reset time.' - )} - - - {localize( - "If the exit spot is equal to the barrier or the new barrier (if a reset occurs), you don't win the payout." - )} - - - ); + TradeTypeTemplate = ; break; case 'callputspread': - TradeTypeTemplate = ( - -

{localize('Spread Up')}

- - {localize( - 'Win maximum payout if the exit spot is higher than or equal to the upper barrier.' - )} - - - {localize( - 'Win up to maximum payout if exit spot is between lower and upper barrier, in proportion to the difference between exit spot and lower barrier.' - )} - - {localize('No payout if exit spot is below or equal to the lower barrier.')} -

{localize('Spread Down')}

- - {localize( - 'Win maximum payout if the exit spot is lower than or equal to the lower barrier.' - )} - - - {localize( - 'Win up to maximum payout if exit spot is between lower and upper barrier, in proportion to the difference between upper barrier and exit spot.' - )} - - {localize('No payout if exit spot is above or equal to the upper barrier.')} -
- ); + TradeTypeTemplate = ; break; case 'tick_high_low': - TradeTypeTemplate = ( - - - {localize( - 'If you select "High Tick", you win the payout if the selected tick is the highest among the next five ticks.' - )} - - - {localize( - 'If you select "Low Tick", you win the payout if the selected tick is the lowest among the next five ticks.' - )} - - - ); + TradeTypeTemplate = ; break; case 'lb_high_low': - TradeTypeTemplate = ( - - - {localize( - 'By purchasing the "High-to-Low" contract, you\'ll win the multiplier times the difference between the high and low over the duration of the contract.' - )} - - - {localize( - 'The high is the highest point ever reached by the market during the contract period.' - )} - - - {localize( - 'The low is the lowest point ever reached by the market during the contract period.' - )} - - - {localize( - 'The close is the latest tick at or before the end time. If you selected a specific end time, the end time is the selected time.' - )} - - - ); + TradeTypeTemplate = ; break; case 'lb_put': - TradeTypeTemplate = ( - - - {localize( - 'By purchasing the "High-to-Close" contract, you\'ll win the multiplier times the difference between the high and close over the duration of the contract.' - )} - - - {localize( - 'The high is the highest point ever reached by the market during the contract period.' - )} - - - {localize( - 'The low is the lowest point ever reached by the market during the contract period.' - )} - - - {localize( - 'The close is the latest tick at or before the end time. If you selected a specific end time, the end time is the selected time.' - )} - - - ); + TradeTypeTemplate = ; break; case 'lb_call': - TradeTypeTemplate = ( - - - {localize( - 'By purchasing the "Close-to-Low" contract, you\'ll win the multiplier times the difference between the close and low over the duration of the contract.' - )} - - - {localize( - 'The high is the highest point ever reached by the market during the contract period.' - )} - - - {localize( - 'The low is the lowest point ever reached by the market during the contract period.' - )} - - - {localize( - 'The close is the latest tick at or before the end time. If you selected a specific end time, the end time is the selected time.' - )} - - - ); + TradeTypeTemplate = ; break; case 'multiplier': TradeTypeTemplate = ( @@ -385,88 +100,14 @@ const TradeCategories = ({ break; case VANILLALONG.CALL: case VANILLALONG.PUT: - TradeTypeTemplate = ( - - - {localize( - 'Vanilla options allow you to predict an upward (bullish) or downward (bearish) direction of the underlying asset by purchasing a "Call" or a "Put".' - )} - - - , - , - ]} - /> - - - ]} - /> - - - {is_vanilla_fx ? ( - , - , - ]} - /> - ) : ( - , - ]} - /> - )} - - - {is_vanilla_fx ? ( - , - ]} - /> - ) : ( - , - ]} - /> - )} - - - ); + TradeTypeTemplate = ; break; default: - TradeTypeTemplate = {localize('Description not found.')}; + TradeTypeTemplate = ( + + + + ); break; } } diff --git a/packages/trader/src/Modules/Contract/Components/Digits/digits.tsx b/packages/trader/src/Modules/Contract/Components/Digits/digits.tsx index b66ecd16b955..cc5fd26df063 100644 --- a/packages/trader/src/Modules/Contract/Components/Digits/digits.tsx +++ b/packages/trader/src/Modules/Contract/Components/Digits/digits.tsx @@ -39,7 +39,7 @@ type TDigits = Pick & { selected_digit?: TTraderStore['last_digit']; trade_type?: TTraderStore['contract_type']; tick?: TTickSpotData; - underlying: TTraderStore['symbol']; + underlying?: TTraderStore['symbol']; }; type TTickStream = NonNullable[number]; type TTickData = diff --git a/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx b/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.tsx similarity index 77% rename from packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx rename to packages/trader/src/Modules/Contract/Containers/contract-replay-widget.tsx index 9396435ce7dc..1df502c0ce86 100644 --- a/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx +++ b/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.tsx @@ -1,10 +1,9 @@ import React from 'react'; import Digits from 'Modules/Contract/Components/Digits'; import InfoBox from 'Modules/Contract/Components/InfoBox'; -import BottomWidgets from '../../SmartChart/Components/bottom-widgets.jsx'; -import TopWidgets from '../../SmartChart/Components/top-widgets.jsx'; +import BottomWidgets from '../../SmartChart/Components/bottom-widgets'; +import TopWidgets from '../../SmartChart/Components/top-widgets'; import { observer, useStore } from '@deriv/stores'; -import { useTraderStore } from 'Stores/useTraderStores'; export const DigitsWidget = observer(() => { const { contract_replay } = useStore(); @@ -24,18 +23,10 @@ export const DigitsWidget = observer(() => { export const InfoBoxWidget = observer(() => { const { contract_replay } = useStore(); - const { is_vanilla } = useTraderStore(); const { contract_store, removeErrorMessage: removeError, error_message } = contract_replay; const { contract_info } = contract_store; - return ( - - ); + return ; }); // Chart widgets passed into SmartCharts diff --git a/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx b/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx index c57529d967c4..32c5f9205ff9 100644 --- a/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx +++ b/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx @@ -34,8 +34,8 @@ import ChartLoader from 'App/Components/Elements/chart-loader'; import ContractDrawer from 'App/Components/Elements/ContractDrawer'; import UnsupportedContractModal from 'App/Components/Elements/Modals/UnsupportedContractModal'; import SmartChartSwitcher from '../../Trading/Containers/smart-chart-switcher.jsx'; -import { ChartBottomWidgets, ChartTopWidgets, DigitsWidget, InfoBoxWidget } from './contract-replay-widget.jsx'; -import ChartMarker from 'Modules/SmartChart/Components/Markers/marker.jsx'; +import { ChartBottomWidgets, ChartTopWidgets, DigitsWidget, InfoBoxWidget } from './contract-replay-widget'; +import ChartMarker from 'Modules/SmartChart/Components/Markers/marker'; import DelayedAccuBarriersMarker from 'Modules/SmartChart/Components/Markers/delayed-accu-barriers-marker'; import allMarkers from 'Modules/SmartChart/Components/all-markers.jsx'; import ChartMarkerBeta from 'Modules/SmartChartBeta/Components/Markers/marker.jsx'; diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/accumulators-chart-elements.spec.tsx b/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/accumulators-chart-elements.spec.tsx index 517c9cf0dd4b..16b7198b48a5 100644 --- a/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/accumulators-chart-elements.spec.tsx +++ b/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/accumulators-chart-elements.spec.tsx @@ -6,7 +6,7 @@ jest.mock('App/Components/Elements/PositionsDrawer/helpers/positions-helper', () filterByContractType: jest.fn(() => true), })); jest.mock('../accumulators-profit-loss-tooltip', () => jest.fn(() =>
AccumulatorsProfitLossTooltip
)); -jest.mock('../marker.jsx', () => jest.fn(() =>
Spot-emphasizing ChartMarker
)); +jest.mock('../marker', () => jest.fn(() =>
Spot-emphasizing ChartMarker
)); describe('AccumulatorsChartElements', () => { const mock_props = { diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/marker-spot-label.spec.tsx b/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/marker-spot-label.spec.tsx deleted file mode 100644 index 420ed80774e4..000000000000 --- a/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/marker-spot-label.spec.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import MarkerSpotLabel from '../marker-spot-label.jsx'; - -describe('MarkerSpotLabel', () => { - it('should have "chart-spot-label__time-value-container--top" class if no "align_label" is passed in the props', () => { - render(); - expect(screen.getByTestId('dt_time_value_container')).toHaveClass( - 'chart-spot-label__time-value-container--top' - ); - }); - - it('should have "chart-spot-label__time-value-container--bottom" class if "align_label" "bottom" is passed in the props', () => { - render(); - expect(screen.getByTestId('dt_time_value_container')).toHaveClass( - 'chart-spot-label__time-value-container--bottom' - ); - }); - - it('should have "chart-spot-label__value-container--won" class if "status" "won" is passed in the props', () => { - render(); - expect(screen.getByTestId('dt_value_container')).toHaveClass('chart-spot-label__value-container--won'); - }); - - it('should have "chart-spot-label__value-container--lost" class if "status" "lost" is passed in the props', () => { - render(); - expect(screen.getByTestId('dt_value_container')).toHaveClass('chart-spot-label__value-container--lost'); - }); - - it('should render "spot_value" with the correct commas if it is passed in the props', () => { - render(); - expect(screen.getByText('290,787')).toBeInTheDocument(); - }); - - it('should render "spot_epoch" with the correct format if it is passed in the props', () => { - render(); - expect(screen.getByText('00:00:22')).toBeInTheDocument(); - }); - - it('should "HoverToggle" if "has_hover_toggle" is passed in the props', async () => { - render(); - expect(screen.getByTestId('dt_marker_hover_container')).toBeInTheDocument(); - }); - - it('should not "HoverToggle" if "has_hover_toggle" is not passed in the props', () => { - render(); - expect(screen.queryByTestId('dt_marker_hover_container')).not.toBeInTheDocument(); - }); -}); diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/marker-spot.spec.tsx b/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/marker-spot.spec.tsx deleted file mode 100644 index b1a4d24685d2..000000000000 --- a/packages/trader/src/Modules/SmartChart/Components/Markers/__tests__/marker-spot.spec.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import MarkerSpot from '../marker-spot.jsx'; - -describe('MarkerSpot Component', () => { - it('should render MarkerSpot component', () => { - render(); - const text = screen.getByText(/3/i); - expect(text).toBeInTheDocument(); - }); - - it('should not has class ".chart-spot__spot--lost" or ".chart-spot__spot--won" if no status is passed in props', () => { - render(); - const text = screen.getByText(/3/i); - expect(text).not.toHaveClass('.chart-spot__spot--lost'); - expect(text).not.toHaveClass('.chart-spot__spot--won'); - }); -}); diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-chart-elements.tsx b/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-chart-elements.tsx index e22dbfdc0dd0..600f479e76ea 100644 --- a/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-chart-elements.tsx +++ b/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-chart-elements.tsx @@ -3,7 +3,7 @@ import React from 'react'; import AccumulatorsProfitLossTooltip from './accumulators-profit-loss-tooltip'; import { ProposalOpenContract } from '@deriv/api-types'; import ChartMarkerBeta from 'Modules/SmartChartBeta/Components/Markers/marker.jsx'; -import ChartMarker from './marker.jsx'; +import ChartMarker from './marker'; type TPositions = { contract_info: Omit< @@ -15,7 +15,7 @@ type TPositions = { type TAccumulatorsChartElements = { all_positions: TPositions[]; - current_spot?: number | null; + current_spot: number; current_spot_time: number; has_crossed_accu_barriers: boolean; should_show_profit_text: React.ComponentProps['should_show_profit_text']; diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/index.js b/packages/trader/src/Modules/SmartChart/Components/Markers/index.js deleted file mode 100644 index 3fea22c76b32..000000000000 --- a/packages/trader/src/Modules/SmartChart/Components/Markers/index.js +++ /dev/null @@ -1 +0,0 @@ -export default from './marker.jsx'; diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/marker-line.jsx b/packages/trader/src/Modules/SmartChart/Components/Markers/marker-line.jsx deleted file mode 100644 index c4a5c7083a7e..000000000000 --- a/packages/trader/src/Modules/SmartChart/Components/Markers/marker-line.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import classNames from 'classnames'; -import { observer } from 'mobx-react'; -import PropTypes from 'prop-types'; -import React from 'react'; -import { Icon } from '@deriv/components'; - -const MarkerLine = ({ label, line_style, marker_config, status }) => { - // TODO: Find a more elegant solution - if (!marker_config) return
; - return ( -
- {label === marker_config.LINE_END.content_config.label && ( - - )} - {label === marker_config.LINE_START.content_config.label && ( - - )} -
- ); -}; - -MarkerLine.propTypes = { - label: PropTypes.string, - line_style: PropTypes.string, - marker_config: PropTypes.object, - status: PropTypes.oneOf(['won', 'lost']), -}; -export default observer(MarkerLine); diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/marker-spot-label.jsx b/packages/trader/src/Modules/SmartChart/Components/Markers/marker-spot-label.jsx deleted file mode 100644 index 0c48266f24cc..000000000000 --- a/packages/trader/src/Modules/SmartChart/Components/Markers/marker-spot-label.jsx +++ /dev/null @@ -1,94 +0,0 @@ -import classNames from 'classnames'; -import { observer } from 'mobx-react'; -import PropTypes from 'prop-types'; -import React from 'react'; -import { Icon, Text } from '@deriv/components'; -import { addComma, toMoment } from '@deriv/shared'; - -import MarkerSpot from './marker-spot.jsx'; - -const MarkerSpotLabel = ({ - align_label, - has_hover_toggle, - is_value_hidden, - spot_className, - spot_count, - spot_epoch, - spot_value, - status, -}) => { - const [show_label, setShowLabel] = React.useState(!has_hover_toggle); - - const handleHoverToggle = () => { - setShowLabel(!show_label); - }; - - let marker_spot = ; - - if (has_hover_toggle) { - marker_spot = ( -
- {marker_spot} -
- ); - } - - return ( -
- {show_label && !is_value_hidden && ( -
-
- {spot_epoch && ( -
- - - {toMoment(+spot_epoch).format('HH:mm:ss')} - -
- )} -
-

{addComma(spot_value)}

-
-
-
- )} - {marker_spot} -
- ); -}; - -MarkerSpotLabel.defaultProps = { - align_label: 'top', - is_value_hidden: false, -}; - -MarkerSpotLabel.propTypes = { - align_label: PropTypes.oneOf(['top', 'bottom']), - has_hover_toggle: PropTypes.bool, - is_value_hidden: PropTypes.bool, - spot_className: PropTypes.string, - spot_count: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - spot_epoch: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - spot_value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - status: PropTypes.oneOf(['won', 'lost']), -}; -export default observer(MarkerSpotLabel); diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/marker-spot.jsx b/packages/trader/src/Modules/SmartChart/Components/Markers/marker-spot.jsx deleted file mode 100644 index a242334713b6..000000000000 --- a/packages/trader/src/Modules/SmartChart/Components/Markers/marker-spot.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import classNames from 'classnames'; -import { observer } from 'mobx-react'; -import PropTypes from 'prop-types'; -import React from 'react'; - -const MarkerSpot = ({ className, spot_count }) => ( -
{spot_count}
-); - -MarkerSpot.propTypes = { - className: PropTypes.string, - spot_count: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), -}; - -export default observer(MarkerSpot); diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/marker.jsx b/packages/trader/src/Modules/SmartChart/Components/Markers/marker.tsx similarity index 72% rename from packages/trader/src/Modules/SmartChart/Components/Markers/marker.jsx rename to packages/trader/src/Modules/SmartChart/Components/Markers/marker.tsx index 9b6b4c89b0e8..7554cf82ef57 100644 --- a/packages/trader/src/Modules/SmartChart/Components/Markers/marker.jsx +++ b/packages/trader/src/Modules/SmartChart/Components/Markers/marker.tsx @@ -1,15 +1,28 @@ import { toJS } from 'mobx'; -import PropTypes from 'prop-types'; import React from 'react'; import { FastMarker } from 'Modules/SmartChart'; -const ChartMarker = ({ marker_config, marker_content_props, is_bottom_widget_visible }) => { +type TChartMarker = { + is_bottom_widget_visible?: boolean; + marker_config: { + ContentComponent: 'div'; + x: string | number; + y: string | number; + }; + marker_content_props: { className: string }; +}; +type TRef = { + setPosition: (position: { epoch: number | null; price: number | null }) => void; + div: HTMLDivElement; +}; + +const ChartMarker = ({ marker_config, marker_content_props, is_bottom_widget_visible }: TChartMarker) => { const { ContentComponent, ...marker_props } = marker_config; // TODO: // - rename x to epoch // - rename y to price - const onRef = ref => { + const onRef = (ref?: TRef) => { if (ref) { // NOTE: null price means vertical line. if (!marker_props.y) { @@ -33,10 +46,4 @@ const ChartMarker = ({ marker_config, marker_content_props, is_bottom_widget_vis return {getMemoizedComponent()}; }; -ChartMarker.propTypes = { - is_bottom_widget_visible: PropTypes.bool, - marker_config: PropTypes.object, - marker_content_props: PropTypes.object, -}; - export default ChartMarker; diff --git a/packages/trader/src/Modules/SmartChart/Components/bottom-widgets.jsx b/packages/trader/src/Modules/SmartChart/Components/bottom-widgets.jsx deleted file mode 100644 index 1b800fc074b2..000000000000 --- a/packages/trader/src/Modules/SmartChart/Components/bottom-widgets.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; - -const BottomWidgets = ({ Widget }) =>
{Widget}
; - -BottomWidgets.propTypes = { - Widget: PropTypes.node, -}; - -export default BottomWidgets; diff --git a/packages/trader/src/Modules/SmartChart/Components/bottom-widgets.tsx b/packages/trader/src/Modules/SmartChart/Components/bottom-widgets.tsx new file mode 100644 index 000000000000..dd64667d5d8d --- /dev/null +++ b/packages/trader/src/Modules/SmartChart/Components/bottom-widgets.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +const BottomWidgets = ({ Widget }: { Widget: React.ReactNode }) =>
{Widget}
; + +export default BottomWidgets; diff --git a/packages/trader/src/Modules/SmartChart/Components/control-widgets.jsx b/packages/trader/src/Modules/SmartChart/Components/control-widgets.jsx deleted file mode 100644 index e62772683ec4..000000000000 --- a/packages/trader/src/Modules/SmartChart/Components/control-widgets.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import { observer, useStore } from '@deriv/stores'; -import { DesktopWrapper } from '@deriv/components'; -import { ChartMode, DrawTools, Share, StudyLegend, Views } from 'Modules/SmartChart'; - -const ControlWidgets = observer(() => { - const { - contract_trade: { updateChartType, updateGranularity }, - } = useStore(); - - return ( - - - updateChartType(type)} - onGranularity={granularity => updateGranularity(granularity)} - /> - - - - - - - ); -}); - -export default ControlWidgets; diff --git a/packages/trader/src/Modules/SmartChart/Components/control-widgets.tsx b/packages/trader/src/Modules/SmartChart/Components/control-widgets.tsx new file mode 100644 index 000000000000..ffee6a00dc3b --- /dev/null +++ b/packages/trader/src/Modules/SmartChart/Components/control-widgets.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { observer, useStore } from '@deriv/stores'; +import { DesktopWrapper } from '@deriv/components'; +import { ChartMode, DrawTools, Share, StudyLegend, Views } from 'Modules/SmartChart'; + +const ControlWidgets = observer(() => { + const { + contract_trade: { updateChartType, updateGranularity }, + } = useStore(); + + return ( + + updateChartType(type)} + onGranularity={(granularity: number) => updateGranularity(granularity)} + /> + + + + + + ); +}); + +export default ControlWidgets; diff --git a/packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.jsx b/packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.tsx similarity index 63% rename from packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.jsx rename to packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.tsx index f16888081bbf..be43d14d0704 100644 --- a/packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.jsx +++ b/packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.tsx @@ -1,11 +1,17 @@ -import PropTypes from 'prop-types'; import React from 'react'; -import { isDesktop, isMobile } from '@deriv/shared'; +import { isDesktop } from '@deriv/shared'; import { ChartMode, DrawTools, Share, StudyLegend, Views, ToolbarWidget } from 'Modules/SmartChart'; -const ToolbarWidgets = ({ position, updateChartType, updateGranularity }) => { +type TToolbarWidgets = { + is_mobile?: boolean; + position?: string; + updateChartType: (type: string) => void; + updateGranularity: (granularity: number) => void; +}; + +const ToolbarWidgets = ({ is_mobile, position, updateChartType, updateGranularity }: TToolbarWidgets) => { return ( - + {isDesktop() && } {isDesktop() && } @@ -15,10 +21,4 @@ const ToolbarWidgets = ({ position, updateChartType, updateGranularity }) => { ); }; -ToolbarWidgets.propTypes = { - position: PropTypes.string, - updateChartType: PropTypes.func, - updateGranularity: PropTypes.func, -}; - export default React.memo(ToolbarWidgets); diff --git a/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx b/packages/trader/src/Modules/SmartChart/Components/top-widgets.tsx similarity index 81% rename from packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx rename to packages/trader/src/Modules/SmartChart/Components/top-widgets.tsx index 65017cd67ea7..767bbe38166f 100644 --- a/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx +++ b/packages/trader/src/Modules/SmartChart/Components/top-widgets.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import ReactDOM from 'react-dom'; import { DesktopWrapper, MobileWrapper, Text } from '@deriv/components'; @@ -8,6 +7,23 @@ import { ChartTitle } from 'Modules/SmartChart'; import { ChartTitleBeta } from 'Modules/SmartChartBeta'; import BuyToastNotification from './buy-toast-notification'; import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +type TTopWidgets = { + InfoBox?: React.ReactNode; + is_digits_widget_active?: boolean; + is_mobile?: boolean; + is_title_enabled?: boolean; + is_beta_chart?: boolean; + onSymbolChange?: ReturnType['onChange']; + open?: boolean; + open_market?: { + category: string | null; + subcategory?: string | null; + }; + theme?: string; + y_axis_width?: number; +}; const RecentTradeInfo = observer(() => { const { contract_trade, client } = useStore(); @@ -17,8 +33,7 @@ const RecentTradeInfo = observer(() => { ? filtered_contracts[filtered_contracts.length - 1] : markers_array[markers_array.length - 1]; if ( - !latest_tick_contract || - !latest_tick_contract.contract_info.tick_stream || + !latest_tick_contract?.contract_info.tick_stream || isAccumulatorContract(latest_tick_contract.contract_info.contract_type) ) return null; @@ -46,7 +61,7 @@ const TopWidgets = ({ open, is_digits_widget_active, is_beta_chart, -}) => { +}: TTopWidgets) => { const ChartTitleComponent = is_beta_chart ? ChartTitleBeta : ChartTitle; const ChartTitleLocal = ( }
, - document.getElementById('app_contents') + document.getElementById('app_contents') as Element | DocumentFragment ); return ( @@ -85,17 +100,4 @@ const TopWidgets = ({ ); }; -TopWidgets.propTypes = { - InfoBox: PropTypes.node, - is_digits_widget_active: PropTypes.bool, - is_mobile: PropTypes.bool, - is_title_enabled: PropTypes.bool, - onSymbolChange: PropTypes.func, - open: PropTypes.bool, - open_market: PropTypes.object, - theme: PropTypes.string, - y_axis_width: PropTypes.number, - is_beta_chart: PropTypes.bool, -}; - export default TopWidgets; diff --git a/packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.jsx b/packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.tsx similarity index 73% rename from packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.jsx rename to packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.tsx index 902f58b46084..66f004b6c4d8 100644 --- a/packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.jsx +++ b/packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Money } from '@deriv/components'; -import { localize } from '@deriv/translations'; +import { Localize } from '@deriv/translations'; import { getExpiryType, getDurationMinMaxValues, getLocalizedBasis } from '@deriv/shared'; -import { MultiplierAmountWidget } from 'Modules/Trading/Components/Form/TradeParams/Multiplier/widgets.jsx'; +import { MultiplierAmountWidget } from 'Modules/Trading/Components/Form/TradeParams/Multiplier/widgets'; import TradeParamsModal from '../../Containers/trade-params-mobile'; import { observer, useStore } from '@deriv/stores'; import { useTraderStore } from 'Stores/useTraderStores'; @@ -24,18 +24,18 @@ const MobileWidget = observer(() => { const contract_expiry_type = getExpiryType(trade_store); const [min_value, max_value] = getDurationMinMaxValues(duration_min_max, contract_expiry_type, duration_unit); - if (contract_expiry_type === 'tick' && duration < min_value) { + if (contract_expiry_type === 'tick' && duration < Number(min_value)) { onChangeUiStore({ name: `duration_${duration_unit}`, value: min_value }); onChange({ target: { name: 'duration', value: min_value } }); } - if (!(duration < min_value) && duration > max_value) { + if (duration >= Number(min_value) && duration > Number(max_value)) { onChangeUiStore({ name: `duration_${duration_unit}`, value: max_value }); onChange({ target: { name: 'duration', value: max_value } }); } }; // tab_index 0 is duration and 1 is amount - const toggleWidget = tab_index => { + const toggleWidget = (tab_index: number) => { setTabIndex(tab_index); setIsOpen(!is_open); }; @@ -43,18 +43,19 @@ const MobileWidget = observer(() => { const getHumanReadableDuration = () => { if (!duration_unit) return ''; const lookup = { - t: [localize('tick'), localize('ticks')], - s: [localize('second'), localize('seconds')], - m: [localize('min'), localize('mins')], - h: [localize('hour'), localize('hours')], - d: [localize('day'), localize('days')], + t: [, ], + s: [, ], + m: [, ], + h: [, ], + d: [, ], }; try { - if (!duration_unit) return ''; - const formatted_duration_unit = +duration === 1 ? lookup[duration_unit][0] : lookup[duration_unit][1]; - - return `${duration} ${formatted_duration_unit}`; + const formatted_duration_unit = + +duration === 1 + ? lookup[duration_unit as keyof typeof lookup][0] + : lookup[duration_unit as keyof typeof lookup][1]; + return [duration, ' ', formatted_duration_unit]; } catch (e) { return ''; } diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/__tests__/widgets.spec.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/__tests__/widgets.spec.tsx similarity index 95% rename from packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/__tests__/widgets.spec.jsx rename to packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/__tests__/widgets.spec.tsx index e1aa98ea3637..fca2afa4f306 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/__tests__/widgets.spec.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/__tests__/widgets.spec.tsx @@ -4,6 +4,7 @@ import { render, screen } from '@testing-library/react'; import { mockStore } from '@deriv/stores'; import { AccumulatorOptionsWidget, MultiplierOptionsWidget } from '../widgets'; import TraderProviders from '../../../../../../../trader-providers'; +import { TCoreStores } from '@deriv/stores/types'; const default_mock_store_accumulators = { modules: { @@ -33,7 +34,7 @@ jest.mock('Modules/Trading/Containers/radio-group-options-modal', () => ); describe('AccumulatorOptionsWidget', () => { - const mockAccumulatorOptionsWidget = mocked_store => { + const mockAccumulatorOptionsWidget = (mocked_store: TCoreStores) => { return ( @@ -73,7 +74,7 @@ describe('AccumulatorOptionsWidget', () => { }); describe('MultiplierOptionsWidget', () => { - const mockMultiplierOptionsWidget = mocked_store => { + const mockMultiplierOptionsWidget = (mocked_store: TCoreStores) => { return ( diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.tsx similarity index 97% rename from packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.jsx rename to packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.tsx index be54335c1579..72ead931c02e 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.tsx @@ -1,11 +1,10 @@ import React from 'react'; import { Checkbox, Dropdown, Popover, PopoverMessageCheckbox } from '@deriv/components'; -import { observer, useStore } from '@deriv/stores'; -import { localize } from '@deriv/translations'; - +import { Localize, localize } from '@deriv/translations'; import Fieldset from 'App/Components/Form/fieldset'; import { onChangeCancellationDuration, onToggleCancellation } from 'Stores/Modules/Trading/Helpers/multiplier'; +import { observer, useStore } from '@deriv/stores'; import { useTraderStore } from 'Stores/useTraderStores'; const CancelDeal = observer(() => { @@ -39,7 +38,7 @@ const CancelDeal = observer(() => { id='dt_cancellation-checkbox_input' onChange={() => onToggleCancellation({ has_cancellation, onChangeMultiple })} name='has_cancellation' - label={localize('Deal cancellation')} + label={} defaultChecked={has_cancellation} /> ); diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration-modal.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration-modal.jsx deleted file mode 100644 index 5885416e322a..000000000000 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration-modal.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Button, Div100vhContainer, Modal, Text } from '@deriv/components'; -import { localize, Localize } from '@deriv/translations'; -import Expiration from './expiration.jsx'; -import { observer, useStore } from '@deriv/stores'; - -const MultipliersExpirationModal = observer(({ is_open, toggleModal }) => { - const { ui } = useStore(); - const { enableApp, disableApp } = ui; - return ( - - - -
- - ]} - /> - -
- -