Skip to content

Commit

Permalink
Maryia/OPT-591/fix: Total profit/loss in Multipliers contract card wi…
Browse files Browse the repository at this point in the history
…th Deal Cancellation (#11057)

* fix: pnl in multipliers card

* test: add tests + make indicator the same as in reports
  • Loading branch information
maryia-deriv committed Nov 3, 2023
1 parent fd6c143 commit 3fc2cf2
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import MultiplierCardBody from '../multiplier-card-body';

type TMockedMultiplierCardBodyProps = Partial<React.ComponentProps<typeof MultiplierCardBody>>;

describe('MultiplierCardBody', () => {
let mock_props: TMockedMultiplierCardBodyProps = {};
const red_indicative_movement_testid = 'dt_indicative_movement_loss';
const green_indicative_movement_testid = 'dt_indicative_movement_profit';
const progress_slider = 'progress_slider';

beforeEach(() => {
mock_props = {
addToast: jest.fn(),
contract_info: {
// 'Total profit/loss' equals to bid_price - buy_price;
buy_price: 10.44,
bid_price: 10,
cancellation: { ask_price: 0.44 },
is_valid_to_cancel: 0,
is_valid_to_sell: 0,
limit_order: {
stop_out: {
display_name: 'Stop out',
order_amount: -10,
order_date: 1698680866,
value: '1942.71',
},
},
sell_price: '10',
status: 'cancelled',
profit: 0,
underlying: '1HZ100V',
},
contract_update: {},
currency: 'USD',
current_focus: '',
getCardLabels: () => ({
BUY_PRICE: 'Buy price:',
CURRENT_STAKE: 'Current stake:',
DEAL_CANCEL_FEE: 'Deal cancel. fee:',
NOT_AVAILABLE: 'N/A',
STAKE: 'Stake:',
STOP_LOSS: 'Stop loss:',
TAKE_PROFIT: 'Take profit:',
TOTAL_PROFIT_LOSS: 'Total Profit/Loss:',
}),
getContractById: jest.fn(),
has_progress_slider: false,
is_mobile: false,
is_sold: true,
onMouseLeave: jest.fn(),
progress_slider: null,
removeToast: jest.fn(),
setCurrentFocus: jest.fn(),
should_show_cancellation_warning: false,
status: 'profit',
toggleCancellationWarning: jest.fn(),
};
});

const testCardContent = (props: TMockedMultiplierCardBodyProps) => {
expect(screen.getByText(props.getCardLabels().BUY_PRICE)).toBeInTheDocument();
expect(screen.getByText(props.getCardLabels().CURRENT_STAKE)).toBeInTheDocument();
expect(screen.getByText(props.getCardLabels().DEAL_CANCEL_FEE)).toBeInTheDocument();
expect(screen.queryByText(props.getCardLabels().NOT_AVAILABLE)).not.toBeInTheDocument();
expect(screen.getByText(props.getCardLabels().STAKE)).toBeInTheDocument();
expect(screen.getByText(props.getCardLabels().STOP_LOSS)).toBeInTheDocument();
expect(screen.getByText(props.getCardLabels().TAKE_PROFIT)).toBeInTheDocument();
expect(screen.getByText(props.getCardLabels().TOTAL_PROFIT_LOSS)).toBeInTheDocument();
};

it('should render the correct content for a Cancelled contract with Deal cancel.fee and negative Total profit/loss', () => {
render(<MultiplierCardBody {...mock_props} />);

testCardContent(mock_props);
expect(screen.getByTestId(red_indicative_movement_testid)).toBeInTheDocument();
});
it('should render a green price movement indicator when Won with positive Total profit/loss', () => {
mock_props.contract_info.bid_price = 10.03;
mock_props.contract_info.buy_price = 10;
mock_props.contract_info.profit = 0.03;
mock_props.contract_info.sell_price = 10.03;
mock_props.contract_info.status = 'sold';
delete mock_props.contract_info.cancellation;

render(<MultiplierCardBody {...mock_props} />);

testCardContent(mock_props);
expect(screen.getByTestId(green_indicative_movement_testid)).toBeInTheDocument();
});
it('should render correct content for an open contract with negative Total profit/loss in mobile', () => {
mock_props.is_mobile = true;
mock_props.contract_info.bid_price = 10.2;
mock_props.contract_info.buy_price = 10.44;
mock_props.contract_info.is_sold = 0;
mock_props.contract_info.is_valid_to_cancel = 1;
mock_props.contract_info.is_valid_to_sell = 1;
mock_props.contract_info.profit = 0.2;
mock_props.contract_info.status = 'open';
mock_props.status = 'profit';
mock_props.is_sold = false;
delete mock_props.contract_info.sell_price;

render(<MultiplierCardBody {...mock_props} />);

testCardContent(mock_props);
expect(screen.getByTestId(red_indicative_movement_testid)).toBeInTheDocument();
});
it('should render progress_slider and N/A in Deal Cancel.fee when contract is open for a crypto asset in mobile', () => {
mock_props.is_mobile = true;
mock_props.contract_info.status = 'open';
mock_props.contract_info.underlying = 'cryBTCUSD';
mock_props.is_sold = false;
mock_props.has_progress_slider = true;
mock_props.progress_slider = progress_slider;
delete mock_props.contract_info.cancellation;
delete mock_props.contract_info.sell_price;

render(<MultiplierCardBody {...mock_props} />);

expect(screen.getByText(mock_props.getCardLabels().NOT_AVAILABLE)).toBeInTheDocument();
expect(screen.getByText(progress_slider)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
isCryptocurrency,
getCancellationPrice,
getLimitOrderAmount,
getTotalProfit,
isValidToCancel,
isValidToSell,
shouldShowCancellation,
Expand Down Expand Up @@ -35,12 +36,12 @@ const MultiplierCardBody = ({
status,
toggleCancellationWarning,
}) => {
const { buy_price, bid_price, profit, limit_order, underlying } = contract_info;

const { buy_price, bid_price, limit_order, underlying } = contract_info;
const { take_profit, stop_loss } = getLimitOrderAmount(contract_update || limit_order);
const cancellation_price = getCancellationPrice(contract_info);
const is_valid_to_cancel = isValidToCancel(contract_info);
const is_valid_to_sell = isValidToSell(contract_info);
const total_profit = getTotalProfit(contract_info);
const {
BUY_PRICE,
CURRENT_STAKE,
Expand All @@ -67,8 +68,8 @@ const MultiplierCardBody = ({
<ContractCardItem header={CURRENT_STAKE} className='dc-contract-card__current-stake'>
<div
className={classNames({
'dc-contract-card--profit': +profit > 0,
'dc-contract-card--loss': +profit < 0,
'dc-contract-card--profit': total_profit > 0,
'dc-contract-card--loss': total_profit < 0,
})}
>
<Money amount={bid_price} currency={currency} />
Expand Down Expand Up @@ -127,17 +128,17 @@ const MultiplierCardBody = ({
className='dc-contract-card-item__total-profit-loss'
header={TOTAL_PROFIT_LOSS}
is_crypto={isCryptocurrency(currency)}
is_loss={+profit < 0}
is_won={+profit > 0}
is_loss={total_profit < 0}
is_won={total_profit > 0}
>
<Money amount={profit} currency={currency} />
<Money amount={Math.abs(total_profit)} currency={currency} />
<div
className={classNames('dc-contract-card__indicative--movement', {
'dc-contract-card__indicative--movement-complete': is_sold,
})}
data-testid={`dt_indicative_movement_${total_profit > 0 ? 'profit' : 'loss'}`}
>
{status === 'profit' && <Icon icon='IcProfit' />}
{status === 'loss' && <Icon icon='IcLoss' />}
{total_profit > 0 ? <Icon icon='IcProfit' /> : <Icon icon='IcLoss' />}
</div>
</ContractCardItem>
</React.Fragment>
Expand Down

1 comment on commit 3fc2cf2

@vercel
Copy link

@vercel vercel bot commented on 3fc2cf2 Nov 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

deriv-app – ./

deriv-app.vercel.app
deriv-app-git-master.binary.sx
binary.sx
deriv-app.binary.sx

Please sign in to comment.