Skip to content

Commit

Permalink
[DTRA] Maryia/WEBREL-14/test: MarketSymbolIconRow + migrate formatSta…
Browse files Browse the repository at this point in the history
…tementTransaction to TS (deriv-com#15105)

* test: MarketSymbolIconRow + migrate formatStatementTransaction to TS

* test: MarketSymbolIconRow finalized
  • Loading branch information
maryia-deriv authored May 27, 2024
1 parent 19daa95 commit 56b8188
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 26 deletions.
1 change: 1 addition & 0 deletions packages/reports/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"@deriv-com/analytics": "1.4.13",
"@deriv/components": "^1.0.0",
"@deriv/deriv-api": "^1.0.15",
"@deriv/api-types": "^1.0.172",
"@deriv/hooks": "^1.0.0",
"@deriv/shared": "^1.0.0",
"@deriv/stores": "^1.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { mockContractInfo } from '@deriv/shared';
import userEvent from '@testing-library/user-event';
import MarketSymbolIconRow from '../market-symbol-icon-row';

jest.mock('@deriv/components', () => ({
...jest.requireActual('@deriv/components'),
Icon: jest.fn(({ icon }: { icon: string }) => <div>{icon}</div>),
IconTradeTypes: jest.fn(({ type }: { type: string }) => <div>{type}</div>),
}));

describe('MarketSymbolIconRow', () => {
const displayedGrowthRate = '1%';
const displayedMultiplier = 'x10';
const mockedSymbolIcon = /IcUnderlying/i;
const mockedTradeTypeIcon = 'call';
const symbolTitle = 'Volatility 100 (1s) Index';
const tradeTypeTitle = 'Rise';
const mockedAccuPayload = mockContractInfo({
shortcode: 'ACCU_1HZ100V_10.00_0_0.01_1_0.000433139675_1715181640',
});
const mockedMultPayload = mockContractInfo({
shortcode: 'MULTUP_1HZ100V_10.00_10_1705570990_4859222399_0_0.00',
});
const mockedRisePayload = mockContractInfo();

it('should render symbol icon and contract type icon when payload has a valid shortcode', () => {
render(<MarketSymbolIconRow payload={mockedRisePayload} />);
expect(screen.getByText(mockedSymbolIcon)).toBeInTheDocument();
expect(screen.getByText(mockedTradeTypeIcon)).toBeInTheDocument();
});
it('should render an unknown icon when payload has no shortcode and an empty/invalid action_type', () => {
render(<MarketSymbolIconRow payload={{}} />);
expect(screen.queryByText(mockedSymbolIcon)).not.toBeInTheDocument();
expect(screen.queryByText(mockedTradeTypeIcon)).not.toBeInTheDocument();
expect(screen.getByTestId('dt_unknown_icon')).toBeInTheDocument();
});
it('should render a popover with a correct symbol name when symbol icon is hovered', () => {
render(<MarketSymbolIconRow payload={mockedRisePayload} />);
const symbolIcon = screen.getByText(mockedSymbolIcon);
userEvent.hover(symbolIcon);
expect(screen.getByText(symbolTitle)).toBeInTheDocument();
});
it('should render a popover with a correct trade type name when trade type icon is hovered', () => {
render(<MarketSymbolIconRow payload={mockedRisePayload} />);
const tradeTypeIcon = screen.getByText(mockedTradeTypeIcon);
userEvent.hover(tradeTypeIcon);
expect(screen.getByText(tradeTypeTitle)).toBeInTheDocument();
});
it('should render multiplier value when payload.shortcode has multiplier value', () => {
render(<MarketSymbolIconRow payload={mockedMultPayload} />);
expect(screen.getByText(displayedMultiplier)).toBeInTheDocument();
});
it('should not render multiplier value when payload.shortcode has multiplier value but should_show_multiplier is false', () => {
render(<MarketSymbolIconRow payload={mockedMultPayload} should_show_multiplier={false} />);
expect(screen.queryByText(displayedMultiplier)).not.toBeInTheDocument();
});
it('should render accumulator % when shortcode in payload.shortcode has growth_rate of 0.01', () => {
render(<MarketSymbolIconRow payload={mockedAccuPayload} />);
expect(screen.getByText(displayedGrowthRate)).toBeInTheDocument();
});
it('should not render accumulator % when payload.shortcode has growth_rate value but should_show_accumulator is false', () => {
render(<MarketSymbolIconRow payload={mockedAccuPayload} should_show_accumulator={false} />);
expect(screen.queryByText(displayedGrowthRate)).not.toBeInTheDocument();
});
it('should render a full contract title when has_full_contract_title is true', () => {
render(<MarketSymbolIconRow payload={mockedRisePayload} has_full_contract_title />);
expect(screen.getByText(symbolTitle)).toBeInTheDocument();
expect(screen.getByText(tradeTypeTitle)).toBeInTheDocument();
});
it('should render an IcCashierDeposit icon when payload.action_type is "deposit"', () => {
render(<MarketSymbolIconRow payload={{ action_type: 'deposit' }} />);
expect(screen.getByText('IcCashierDeposit')).toBeInTheDocument();
});
it('should render a custom icon if it is passed when payload.action_type is "deposit"', () => {
render(<MarketSymbolIconRow payload={{ action_type: 'deposit' }} icon='IcCustomIcon' />);
expect(screen.getByText('IcCustomIcon')).toBeInTheDocument();
});
it('should render an IcCashierWithdrawal icon when payload.action_type is "withdrawal"', () => {
render(<MarketSymbolIconRow payload={{ action_type: 'withdrawal' }} />);
expect(screen.getByText('IcCashierWithdrawal')).toBeInTheDocument();
});
it('should render an IcAccountTransferColored icon when payload.action_type is "transfer"', () => {
render(<MarketSymbolIconRow payload={{ action_type: 'transfer' }} />);
expect(screen.getByText('IcAccountTransferColored')).toBeInTheDocument();
});
it('should render an IcCashierDp2p icon when payload.action_type is "hold"', () => {
render(<MarketSymbolIconRow payload={{ action_type: 'hold' }} />);
expect(screen.getByText('IcCashierDp2p')).toBeInTheDocument();
});
it('should render an IcCashierDp2p icon when payload.action_type is "release"', () => {
render(<MarketSymbolIconRow payload={{ action_type: 'release' }} />);
expect(screen.getByText('IcCashierDp2p')).toBeInTheDocument();
});
it('should render an IcAdjustment icon when payload.action_type is "adjustment"', () => {
render(<MarketSymbolIconRow payload={{ action_type: 'adjustment' }} />);
expect(screen.getByText('IcAdjustment')).toBeInTheDocument();
});
});
26 changes: 14 additions & 12 deletions packages/reports/src/Components/market-symbol-icon-row.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import React from 'react';
import { extractInfoFromShortcode, getMarketName, getTradeTypeName, isHighLow } from '@deriv/shared';
import { TContractInfo, extractInfoFromShortcode, getMarketName, getTradeTypeName, isHighLow } from '@deriv/shared';
import { Icon, Popover, IconTradeTypes } from '@deriv/components';
import classNames from 'classnames';
import { formatStatementTransaction } from 'Stores/Modules/Statement/Helpers/format-response';

type TStatementData = ReturnType<typeof formatStatementTransaction>;

type TMarketSymbolIconRow = {
has_full_contract_title?: boolean;
icon?: string | null;
payload: {
shortcode: string;
display_name: string;
action_type: string;
};
payload: Partial<TContractInfo | TStatementData>;
should_show_multiplier?: boolean;
should_show_accumulator?: boolean;
};
Expand All @@ -22,8 +21,8 @@ const MarketSymbolIconRow = ({
should_show_accumulator = true,
should_show_multiplier = true,
}: TMarketSymbolIconRow) => {
const should_show_category_icon = typeof payload.shortcode === 'string';
const info_from_shortcode = extractInfoFromShortcode(payload.shortcode);
const should_show_category_icon = typeof (payload as TContractInfo).shortcode === 'string';
const info_from_shortcode = extractInfoFromShortcode((payload as TContractInfo).shortcode ?? '');
const is_high_low = isHighLow({ shortcode_info: info_from_shortcode });
const category_label = getTradeTypeName(info_from_shortcode.category, {
isHighLow: is_high_low,
Expand Down Expand Up @@ -59,7 +58,7 @@ const MarketSymbolIconRow = ({
size={32}
/>
</Popover>
{has_full_contract_title && payload.display_name}
{has_full_contract_title && (payload as TContractInfo).display_name}
</div>

<div className='market-symbol-icon-category'>
Expand Down Expand Up @@ -90,7 +89,10 @@ const MarketSymbolIconRow = ({
)}
</div>
);
} else if (['deposit', 'hold', 'release', 'withdrawal', 'transfer'].includes(payload.action_type)) {
} else if (
'action_type' in payload &&
['deposit', 'hold', 'release', 'withdrawal', 'transfer'].includes(payload.action_type ?? '')
) {
return (
<div className='market-symbol-icon'>
{payload.action_type === 'deposit' && <Icon icon={icon || 'IcCashierDeposit'} size={32} />}
Expand All @@ -101,7 +103,7 @@ const MarketSymbolIconRow = ({
)}
</div>
);
} else if (['adjustment'].includes(payload.action_type)) {
} else if (['adjustment'].includes((payload as TStatementData).action_type ?? '')) {
return (
<div className='market-symbol-icon'>
<Icon icon='IcAdjustment' size={32} />
Expand All @@ -110,7 +112,7 @@ const MarketSymbolIconRow = ({
}

return (
<svg width='32' height='32' className='unknown-icon'>
<svg width='32' height='32' className='unknown-icon' data-testid='dt_unknown_icon'>
<rect width='32' height='32' />
</svg>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,42 @@
import { formatMoney, toTitleCase, toMoment, getMarketInformation, getSymbolDisplayName } from '@deriv/shared';
import { localize } from '@deriv/translations';
import { ActiveSymbols, Statement } from '@deriv/api-types';

export const formatStatementTransaction = (transaction, currency, active_symbols = []) => {
export const formatStatementTransaction = (
transaction: NonNullable<Statement['transactions']>[number],
currency: string,
active_symbols: ActiveSymbols = []
) => {
const { action_type, app_id, contract_id, longcode, purchase_time, withdrawal_details } = transaction;
const format_string = 'DD MMM YYYY HH:mm:ss';
const transaction_time = toMoment(transaction.transaction_time).format(format_string);
const payout = parseFloat(transaction.payout);
const amount = parseFloat(transaction.amount);
const balance = parseFloat(transaction.balance_after);
const payout = transaction.payout ?? NaN;
const amount = transaction.amount ?? NaN;
const balance = transaction.balance_after ?? NaN;
const should_exclude_currency = true;
const shortcode = ['buy', 'sell'].includes(transaction.action_type) ? transaction.shortcode : null;
const shortcode = ['buy', 'sell'].includes(action_type ?? '') ? transaction.shortcode : null;
const display_name = shortcode
? getSymbolDisplayName(active_symbols, getMarketInformation(shortcode).underlying)
: '';

return {
action: localize(toTitleCase(transaction.action_type) /* localize-ignore */), // handled in static_strings_app.js: 'Buy', 'Sell', 'Deposit', 'Withdrawal'
action: localize(toTitleCase(action_type ?? '')), // 'Buy', 'Sell', 'Deposit', 'Withdrawal'
date: transaction_time,
display_name,
refid: transaction.transaction_id,
payout: isNaN(payout) ? '-' : formatMoney(currency, payout, should_exclude_currency),
amount: isNaN(amount) ? '-' : formatMoney(currency, amount, should_exclude_currency),
balance: isNaN(balance) ? '-' : formatMoney(currency, balance, should_exclude_currency),
desc: transaction.longcode.replace(/\n/g, '<br />'),
id: transaction.contract_id,
app_id: transaction.app_id,
desc: longcode?.replace(/\n/g, '<br />'),
id: contract_id,
app_id,
shortcode,
action_type: transaction.action_type,
purchase_time: transaction.purchase_time,
action_type,
purchase_time,
transaction_time: transaction.transaction_time,
...(transaction.withdrawal_details && {
withdrawal_details: transaction.withdrawal_details,
longcode: transaction.longcode,
...(withdrawal_details && {
withdrawal_details,
longcode,
}),
};
};

0 comments on commit 56b8188

Please sign in to comment.