Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Kate/90808/90829/ To migrate turbos-card-body, turbos-trade-description, barrier-selector and barrier-list to TS together with their tests #102

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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { render, screen } from '@testing-library/react';
import { TContractInfo } from '@deriv/shared/src/utils/contract/contract-types';
import TurbosCardBody from '../turbos-card-body';

const contract_info = {
const contract_info: TContractInfo = {
contract_id: 1,
buy_price: '1044.00',
bid_price: 1044.02,
buy_price: 1044.0,
profit: 50,
limit_order: null,
barrier: '10904.80',
current_spot_display_value: '1046.80',
sell_spot: '1046.80',
sell_spot: 1046.8,
entry_spot: 1054,
is_valid_to_sell: 1,
};

const mockCardLabels = () => ({
Expand All @@ -30,25 +33,35 @@ describe('TurbosCardBody', () => {
addToast: jest.fn(),
connectWithContractUpdate: jest.fn(),
contract_info,
contract_update: contract_info,
contract_update: {
take_profit: {
display_name: 'Take profit',
order_amount: 0,
order_date: 1678948046,
},
},
currency: 'USD',
current_focus: null,
error_message_alignment: 'left',
getCardLabels: mockCardLabels,
getContractById: jest.fn(),
is_sold: false,
is_turbos: true,
is_open_positions: false,
onMouseLeave: jest.fn(),
removeToast: jest.fn(),
setCurrentFocus: jest.fn(),
status: 'profit',
progress_slider_mobile_el: false,
};
beforeAll(() => {
(ReactDOM.createPortal as jest.Mock) = jest.fn(component => {
return component;
});
});

// is_open_positions = false && is_sold = false
it('renders stake amount correctly', () => {
render(<TurbosCardBody {...mock_props} contract_info={contract_info} currency='USD' />);
render(<TurbosCardBody {...mock_props} />);
const stake_header = screen.getByText(mockCardLabels().STAKE);
expect(stake_header).toBeInTheDocument();
const stake_amount = screen.getByText('1,044.00');
Expand All @@ -66,38 +79,28 @@ describe('TurbosCardBody', () => {

const take_profit_header = screen.getByText(mockCardLabels().TAKE_PROFIT);
expect(take_profit_header).toBeInTheDocument();
const take_profit_amount = screen.getByText('0.00');
const take_profit_amount = screen.getByText('0.02');
expect(take_profit_amount).toBeInTheDocument();

const total_profit_loss_header = screen.getByText(mockCardLabels().TOTAL_PROFIT_LOSS);
expect(total_profit_loss_header).toBeInTheDocument();
const total_profit_loss_amount = screen.getByText('0.00');
const total_profit_loss_amount = screen.getByText('0.02');
expect(total_profit_loss_amount).toBeInTheDocument();
});

// is_open_positions = true && is_sold = false
it('renders potential profit/loss correctly for open positions', () => {
render(
<TurbosCardBody
{...mock_props}
contract_info={contract_info}
currency='USD'
is_open_positions
is_sold={false}
/>
);
render(<TurbosCardBody {...mock_props} is_open_positions />);

const potential_profit_loss_header = screen.getByText(mockCardLabels().POTENTIAL_PROFIT_LOSS);
expect(potential_profit_loss_header).toBeInTheDocument();
const potential_profit_loss_amount = screen.getByText('0.00');
const potential_profit_loss_amount = screen.getByText('0.02');
expect(potential_profit_loss_amount).toBeInTheDocument();
});

// is_open_positions = true && is_sold = true
it('renders headers when contract is sold', () => {
render(
<TurbosCardBody {...mock_props} contract_info={contract_info} currency='USD' is_open_positions is_sold />
);
render(<TurbosCardBody {...mock_props} is_open_positions is_sold />);

const profit_loss_header = screen.getByText(mockCardLabels().PROFIT_LOSS);
expect(profit_loss_header).toBeInTheDocument();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Money from '../../money';
import { ResultStatusIcon } from '../result-overlay/result-overlay.jsx';
import ProgressSliderMobile from '../../progress-slider-mobile';
import MultiplierCardBody from './multiplier-card-body.jsx';
import TurbosCardBody from './turbos-card-body.jsx';
import TurbosCardBody from './turbos-card-body';

const ContractCardBody = ({
addToast,
Expand All @@ -27,7 +27,6 @@ const ContractCardBody = ({
is_mobile,
is_multiplier,
is_turbos,
is_positions,
is_sold,
onMouseLeave,
removeToast,
Expand Down Expand Up @@ -97,10 +96,7 @@ const ContractCardBody = ({
is_sold={is_sold}
onMouseLeave={onMouseLeave}
status={status}
is_mobile={is_mobile}
is_open_positions={is_open_positions}
is_positions={is_positions}
is_turbos={is_turbos}
removeToast={removeToast}
setCurrentFocus={setCurrentFocus}
progress_slider_mobile_el={progress_slider_mobile_el}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import { isCryptocurrency, getLimitOrderAmount, getTotalProfit, isValidToSell } from '@deriv/shared';
import ContractCardItem from './contract-card-item.jsx';
Expand All @@ -8,6 +7,35 @@ import Icon from '../../icon';
import MobileWrapper from '../../mobile-wrapper';
import Money from '../../money';
import { ResultStatusIcon } from '../result-overlay/result-overlay.jsx';
import { TContractInfo, TGetContractUpdateConfig } from '@deriv/shared/src/utils/contract/contract-types';
import { TContractStore } from '@deriv/shared/src/utils/helpers/validation-rules';

type TToastConfig = {
maryia-deriv marked this conversation as resolved.
Show resolved Hide resolved
key?: string;
content: string;
timeout?: number;
is_bottom?: boolean;
type: string;
};

type TTurbosCardBody = {
addToast: (toast_config: TToastConfig) => void;
connectWithContractUpdate?: (Component: React.ComponentType) => React.ComponentType;
contract_info: TContractInfo;
contract_update?: TGetContractUpdateConfig['contract_update'];
currency: string;
current_focus?: string | null;
error_message_alignment?: string;
getCardLabels: () => { [key: string]: string };
getContractById: (contract_id: number) => TContractStore;
is_sold: boolean;
is_open_positions?: boolean;
onMouseLeave: () => void;
removeToast: (key: string) => void;
progress_slider_mobile_el: React.ReactNode;
setCurrentFocus: (value: string | null) => void;
status: string | null;
};

const TurbosCardBody = ({
addToast,
Expand All @@ -20,18 +48,16 @@ const TurbosCardBody = ({
getCardLabels,
getContractById,
is_sold,
is_turbos,
is_open_positions,
onMouseLeave,
removeToast,
progress_slider_mobile_el,
setCurrentFocus,
status,
progress_slider_mobile_el,
}) => {
}: TTurbosCardBody) => {
const total_profit = getTotalProfit(contract_info);
const { buy_price, profit, limit_order, barrier, current_spot_display_value, sell_spot, entry_spot } =
contract_info;
const { take_profit } = getLimitOrderAmount(contract_update || limit_order);
const { buy_price, profit, barrier, current_spot_display_value, sell_spot, entry_spot } = contract_info;
const { take_profit } = contract_update ? getLimitOrderAmount(contract_update) : { take_profit: null };
const is_valid_to_sell = isValidToSell(contract_info);
const {
BARRIER_LEVEL,
Expand All @@ -48,9 +74,8 @@ const TurbosCardBody = ({
return (
<React.Fragment>
<div
className={classNames('dc-contract-card-items-wrapper', {
'dc-contract-card--turbos': is_turbos,
'dc-contract-card--turbos-open-positions': is_open_positions && is_turbos,
className={classNames('dc-contract-card-items-wrapper dc-contract-card--turbos', {
'dc-contract-card--turbos-open-positions': is_open_positions,
})}
>
<ContractCardItem
Expand Down Expand Up @@ -192,26 +217,4 @@ const TurbosCardBody = ({
);
};

TurbosCardBody.propTypes = {
addToast: PropTypes.func,
connectWithContractUpdate: PropTypes.func,
contract_info: PropTypes.object,
contract_update: PropTypes.object,
currency: PropTypes.string,
current_focus: PropTypes.string,
error_message_alignment: PropTypes.string,
getCardLabels: PropTypes.func,
getContractById: PropTypes.func,
is_sold: PropTypes.bool,
is_turbos: PropTypes.bool,
is_mobile: PropTypes.bool,
is_open_positions: PropTypes.bool,
is_positions: PropTypes.bool,
onMouseLeave: PropTypes.func,
removeToast: PropTypes.func,
progress_slider_mobile_el: PropTypes.node,
setCurrentFocus: PropTypes.func,
status: PropTypes.string,
};

export default React.memo(TurbosCardBody);
53 changes: 39 additions & 14 deletions packages/shared/src/utils/contract/contract-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,55 @@ export type TIsEnded = Partial<TGetFinalPrice> & {
};

export type TContractInfo = {
tick_stream?: TTickItem[];
account_id?: number;
barrier?: string;
barrier_count?: number;
bid_price: number;
buy_price: number;
cancellation?: {
ask_price?: number;
date_expiry?: number;
};
status?: TStatus;
is_expired?: 0 | 1;
is_settleable?: 0 | 1;
is_valid_to_cancel?: 0 | 1;
contract_id: number;
contract_type?: string;
currency?: string;
current_spot?: number;
current_spot_display_value?: string;
current_spot_time?: number;
date_expiry?: number;
date_settlement?: number;
date_start?: number;
display_name?: string;
entry_spot?: number;
profit?: number;
entry_tick_time?: number;
entry_spot_display_value?: string;
entry_tick?: number;
current_spot_time?: number;
current_spot?: number;
barrier?: string;
contract_type?: string;
entry_tick_display_value?: string;
entry_tick_time?: number;
exit_tick_time?: number;
date_expiry?: number;
expiry_time?: number;
id?: string;
is_expired?: 0 | 1;
is_forward_starting?: 0 | 1;
is_intraday?: number;
is_path_dependent?: 0 | 1;
is_settleable?: 0 | 1;
is_sold?: number;
is_valid_to_cancel?: 0 | 1;
is_valid_to_sell: 0 | 1;
longcode?: string;
profit: number;
profit_percentage?: number;
purchase_time?: number;
sell_time?: number | null;
sell_spot?: number;
shortcode?: string;
status?: TStatus;
tick_count?: number;
date_start?: number;
is_forward_starting?: 0 | 1;
tick_stream?: TTickItem[];
transaction_ids?: { buy?: number };
underlying?: string;
validation_error?: string;
validation_error_code?: string;
};

export type TIsValidToSell = TIsEnded & {
Expand Down
13 changes: 12 additions & 1 deletion packages/shared/src/utils/helpers/logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,18 @@ type TIsSoldBeforeStart = Required<Pick<TContractInfo, 'sell_time' | 'date_start

type TIsStarted = Required<Pick<TContractInfo, 'is_forward_starting' | 'current_spot_time' | 'date_start'>>;

type TGetEndTime = Pick<TContractInfo, 'is_expired' | 'sell_time' | 'status' | 'tick_count'> &
type TGetEndTime = Pick<
TContractInfo,
| 'is_expired'
| 'sell_time'
| 'status'
| 'tick_count'
| 'bid_price'
| 'buy_price'
| 'contract_id'
| 'is_valid_to_sell'
| 'profit'
> &
Required<Pick<TContractInfo, 'date_expiry' | 'exit_tick_time' | 'is_path_dependent'>>;

type TGetBuyPrice = {
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/utils/helpers/validation-rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getTotalProfit } from '../contract';
import { TGetTotalProfit } from '../contract/contract-types';
import { getBuyPrice } from './logic';

type TContractStore = {
export type TContractStore = {
contract_update_stop_loss?: number;
contract_info: TGetTotalProfit;
contract_update_take_profit?: string;
Expand Down
12 changes: 6 additions & 6 deletions packages/stores/src/useStore.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import React, { createContext, PropsWithChildren, useContext, useEffect, useMemo } from 'react';
import React from 'react';
import { TRootStore } from '../types';
import { CounterStore } from './stores';

export type TStores = TRootStore & {
counter: CounterStore;
};

const StoreContext = createContext<TStores | null>(null);
const StoreContext = React.createContext<TStores | null>(null);

const StoreProvider = ({ children, store }: PropsWithChildren<{ store: TRootStore }>) => {
const memoizedValue = useMemo(
const StoreProvider = ({ children, store }: React.PropsWithChildren<{ store: TRootStore }>) => {
const memoizedValue = React.useMemo(
() => ({
...store,
counter: new CounterStore(),
}),
[store]
);

useEffect(() => {
React.useEffect(() => {
return () => {
return memoizedValue.counter.unmount();
};
Expand All @@ -27,7 +27,7 @@ const StoreProvider = ({ children, store }: PropsWithChildren<{ store: TRootStor
};

const useStore = () => {
const store = useContext(StoreContext);
const store = React.useContext(StoreContext);

if (!store) {
throw new Error('useStore must be used within StoreContext');
Expand Down
5 changes: 5 additions & 0 deletions packages/trader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
"devDependencies": {
"@babel/eslint-parser": "^7.17.0",
"@babel/preset-react": "^7.16.7",
"@testing-library/jest-dom": "^5.12.0",
"@testing-library/react": "^12.0.0",
"@testing-library/react-hooks": "^7.0.2",
"@testing-library/user-event": "^13.5.0",
"@types/react": "^18.0.7",
"@types/react-dom": "^18.0.0",
"babel-loader": "^8.1.0",
Expand Down Expand Up @@ -85,6 +89,7 @@
"@deriv/deriv-charts": "1.1.5",
"@deriv/reports": "^1.0.0",
"@deriv/shared": "^1.0.0",
"@deriv/stores": "^1.0.0",
"@deriv/translations": "^1.0.0",
"@types/classnames": "^2.2.11",
"@types/react-loadable": "^5.5.6",
Expand Down
Loading