diff --git a/apps/console-lite-e2e/src/integration/portfolio-page.test.ts b/apps/console-lite-e2e/src/integration/portfolio-page.test.ts index 37ad33eab..6749b99db 100644 --- a/apps/console-lite-e2e/src/integration/portfolio-page.test.ts +++ b/apps/console-lite-e2e/src/integration/portfolio-page.test.ts @@ -66,7 +66,9 @@ describe('Portfolio page tabs', { tags: '@smoke' }, () => { it('data should be properly rendered', () => { cy.get('.ag-center-cols-container .ag-row').should('have.length', 5); - cy.contains('.ag-center-cols-container button', 'tEURO').click(); + cy.get('[role="gridcell"][col-id="account-asset"] button') + .contains('tEURO') + .click(); cy.getByTestId('dialog-title').should( 'have.text', 'Asset details - tEURO' diff --git a/libs/fills/src/lib/fills-table.spec.tsx b/libs/fills/src/lib/fills-table.spec.tsx index a4b9008ee..51175e234 100644 --- a/libs/fills/src/lib/fills-table.spec.tsx +++ b/libs/fills/src/lib/fills-table.spec.tsx @@ -1,4 +1,5 @@ import { act, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { getDateTimeFormat } from '@vegaprotocol/react-helpers'; import * as Schema from '@vegaprotocol/types'; import type { PartialDeep } from 'type-fest'; @@ -57,8 +58,8 @@ describe('FillsTable', () => { const expectedHeaders = [ 'Market', 'Size', - 'Value', - 'Filled value', + 'Price', + 'Notional', 'Role', 'Fee', 'Date', @@ -82,7 +83,7 @@ describe('FillsTable', () => { }, }); - render(); + render(); await waitForGridToBeInTheDOM(); await waitForDataToHaveLoaded(); @@ -179,4 +180,38 @@ describe('FillsTable', () => { .find((c) => c.getAttribute('col-id') === 'aggressor') ).toHaveTextContent('Maker'); }); + + it('should render tooltip over fees', async () => { + const partyId = 'party-id'; + const takerFill = generateFill({ + seller: { + id: partyId, + }, + aggressor: Schema.Side.SIDE_SELL, + }); + act(() => { + render(); + }); + await waitForGridToBeInTheDOM(); + await waitForDataToHaveLoaded(); + + const feeCell = screen + .getAllByRole('gridcell') + .find( + (c) => + c.getAttribute('col-id') === + 'market.tradableInstrument.instrument.product' + ); + + await waitFor(() => { + expect(feeCell).toBeInTheDocument(); + }); + act(() => { + userEvent.hover(feeCell as HTMLElement); + }); + + await waitFor(() => { + expect(screen.getByTestId('fee-breakdown-tooltip')).toBeInTheDocument(); + }); + }); }); diff --git a/libs/fills/src/lib/fills-table.tsx b/libs/fills/src/lib/fills-table.tsx index 5fdbe1755..b2d1724ab 100644 --- a/libs/fills/src/lib/fills-table.tsx +++ b/libs/fills/src/lib/fills-table.tsx @@ -1,4 +1,9 @@ -import type { AgGridReact } from 'ag-grid-react'; +import type { + AgGridReact, + AgGridReactProps, + AgReactUiProps, +} from 'ag-grid-react'; +import type { ITooltipParams } from 'ag-grid-community'; import { addDecimal, addDecimalsFormatNumber, @@ -15,7 +20,6 @@ import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit'; import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit'; import { forwardRef } from 'react'; import BigNumber from 'bignumber.js'; -import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react'; import type { Trade } from './fills-data-provider'; export type Props = (AgGridReactProps | AgReactUiProps) & { @@ -31,6 +35,8 @@ export const FillsTable = forwardRef( defaultColDef={{ flex: 1, resizable: true }} style={{ width: '100%', height: '100%' }} getRowId={({ data }) => data?.id} + tooltipShowDelay={0} + tooltipHideDelay={2000} {...props} > ( valueFormatter={formatSize(partyId)} /> ( field="market.tradableInstrument.instrument.product" valueFormatter={formatFee(partyId)} type="rightAligned" + tooltipField="market.tradableInstrument.instrument.product" + tooltipComponent={FeesBreakdownTooltip} + tooltipComponentParams={{ partyId }} /> { @@ -210,3 +218,50 @@ const formatFee = (partyId: string) => { return `${totalFees} ${asset.symbol}`; }; }; + +const FeesBreakdownTooltip = ({ + data, + value, + valueFormatted, + partyId, +}: ITooltipParams & { partyId?: string }) => { + if (!value?.settlementAsset || !data) { + return null; + } + const asset = value.settlementAsset; + let feesObj; + if (data?.buyer.id === partyId) { + feesObj = data?.buyerFee; + } else if (data?.seller.id === partyId) { + feesObj = data?.sellerFee; + } else { + return null; + } + + return ( +
+
+
{t('Infrastructure fee')}
+
+ {addDecimalsFormatNumber(feesObj.infrastructureFee, asset.decimals)}{' '} + {asset.symbol} +
+
{t('Liquidity fee')}
+
+ {addDecimalsFormatNumber(feesObj.liquidityFee, asset.decimals)}{' '} + {asset.symbol} +
+
{t('Maker fee')}
+
+ {addDecimalsFormatNumber(feesObj.makerFee, asset.decimals)}{' '} + {asset.symbol} +
+
{t('Total fees')}
+
{valueFormatted}
+
+
+ ); +};