From 56b818847769e52cfe5b8a85b8730631a44f846b Mon Sep 17 00:00:00 2001 From: Maryia <103177211+maryia-deriv@users.noreply.github.com> Date: Mon, 27 May 2024 18:21:57 +0300 Subject: [PATCH] [DTRA] Maryia/WEBREL-14/test: MarketSymbolIconRow + migrate formatStatementTransaction to TS (#15105) * test: MarketSymbolIconRow + migrate formatStatementTransaction to TS * test: MarketSymbolIconRow finalized --- packages/reports/package.json | 1 + .../__tests__/market-symbol-icon-row.spec.tsx | 100 ++++++++++++++++++ .../src/Components/market-symbol-icon-row.tsx | 26 ++--- ...{format-response.js => format-response.ts} | 34 +++--- 4 files changed, 135 insertions(+), 26 deletions(-) create mode 100644 packages/reports/src/Components/__tests__/market-symbol-icon-row.spec.tsx rename packages/reports/src/Stores/Modules/Statement/Helpers/{format-response.js => format-response.ts} (51%) diff --git a/packages/reports/package.json b/packages/reports/package.json index 8583ef9d2675..4d3b7b991ea2 100644 --- a/packages/reports/package.json +++ b/packages/reports/package.json @@ -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", diff --git a/packages/reports/src/Components/__tests__/market-symbol-icon-row.spec.tsx b/packages/reports/src/Components/__tests__/market-symbol-icon-row.spec.tsx new file mode 100644 index 000000000000..4190a1c1dcc9 --- /dev/null +++ b/packages/reports/src/Components/__tests__/market-symbol-icon-row.spec.tsx @@ -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 }) =>
{icon}
), + IconTradeTypes: jest.fn(({ type }: { type: string }) =>
{type}
), +})); + +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(); + 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(); + 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(); + 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(); + 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(); + expect(screen.getByText(displayedMultiplier)).toBeInTheDocument(); + }); + it('should not render multiplier value when payload.shortcode has multiplier value but should_show_multiplier is false', () => { + render(); + expect(screen.queryByText(displayedMultiplier)).not.toBeInTheDocument(); + }); + it('should render accumulator % when shortcode in payload.shortcode has growth_rate of 0.01', () => { + render(); + expect(screen.getByText(displayedGrowthRate)).toBeInTheDocument(); + }); + it('should not render accumulator % when payload.shortcode has growth_rate value but should_show_accumulator is false', () => { + render(); + expect(screen.queryByText(displayedGrowthRate)).not.toBeInTheDocument(); + }); + it('should render a full contract title when has_full_contract_title is true', () => { + render(); + expect(screen.getByText(symbolTitle)).toBeInTheDocument(); + expect(screen.getByText(tradeTypeTitle)).toBeInTheDocument(); + }); + it('should render an IcCashierDeposit icon when payload.action_type is "deposit"', () => { + render(); + expect(screen.getByText('IcCashierDeposit')).toBeInTheDocument(); + }); + it('should render a custom icon if it is passed when payload.action_type is "deposit"', () => { + render(); + expect(screen.getByText('IcCustomIcon')).toBeInTheDocument(); + }); + it('should render an IcCashierWithdrawal icon when payload.action_type is "withdrawal"', () => { + render(); + expect(screen.getByText('IcCashierWithdrawal')).toBeInTheDocument(); + }); + it('should render an IcAccountTransferColored icon when payload.action_type is "transfer"', () => { + render(); + expect(screen.getByText('IcAccountTransferColored')).toBeInTheDocument(); + }); + it('should render an IcCashierDp2p icon when payload.action_type is "hold"', () => { + render(); + expect(screen.getByText('IcCashierDp2p')).toBeInTheDocument(); + }); + it('should render an IcCashierDp2p icon when payload.action_type is "release"', () => { + render(); + expect(screen.getByText('IcCashierDp2p')).toBeInTheDocument(); + }); + it('should render an IcAdjustment icon when payload.action_type is "adjustment"', () => { + render(); + expect(screen.getByText('IcAdjustment')).toBeInTheDocument(); + }); +}); diff --git a/packages/reports/src/Components/market-symbol-icon-row.tsx b/packages/reports/src/Components/market-symbol-icon-row.tsx index 90be4ce2a2f6..0955b12451d7 100644 --- a/packages/reports/src/Components/market-symbol-icon-row.tsx +++ b/packages/reports/src/Components/market-symbol-icon-row.tsx @@ -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; type TMarketSymbolIconRow = { has_full_contract_title?: boolean; icon?: string | null; - payload: { - shortcode: string; - display_name: string; - action_type: string; - }; + payload: Partial; should_show_multiplier?: boolean; should_show_accumulator?: boolean; }; @@ -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, @@ -59,7 +58,7 @@ const MarketSymbolIconRow = ({ size={32} /> - {has_full_contract_title && payload.display_name} + {has_full_contract_title && (payload as TContractInfo).display_name}
@@ -90,7 +89,10 @@ const MarketSymbolIconRow = ({ )}
); - } 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 (
{payload.action_type === 'deposit' && } @@ -101,7 +103,7 @@ const MarketSymbolIconRow = ({ )}
); - } else if (['adjustment'].includes(payload.action_type)) { + } else if (['adjustment'].includes((payload as TStatementData).action_type ?? '')) { return (
@@ -110,7 +112,7 @@ const MarketSymbolIconRow = ({ } return ( - + ); diff --git a/packages/reports/src/Stores/Modules/Statement/Helpers/format-response.js b/packages/reports/src/Stores/Modules/Statement/Helpers/format-response.ts similarity index 51% rename from packages/reports/src/Stores/Modules/Statement/Helpers/format-response.js rename to packages/reports/src/Stores/Modules/Statement/Helpers/format-response.ts index 3111f2e37825..131c20778883 100644 --- a/packages/reports/src/Stores/Modules/Statement/Helpers/format-response.js +++ b/packages/reports/src/Stores/Modules/Statement/Helpers/format-response.ts @@ -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[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, '
'), - id: transaction.contract_id, - app_id: transaction.app_id, + desc: longcode?.replace(/\n/g, '
'), + 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, }), }; };