diff --git a/apps/trading-e2e/src/integration/trading-accounts.cy.ts b/apps/trading-e2e/src/integration/trading-accounts.cy.ts index 923c0b99a..2592bea40 100644 --- a/apps/trading-e2e/src/integration/trading-accounts.cy.ts +++ b/apps/trading-e2e/src/integration/trading-accounts.cy.ts @@ -1,3 +1,5 @@ +import { checkSorting } from '@vegaprotocol/cypress'; + beforeEach(() => { cy.mockTradingPage(); cy.mockWeb3Provider(); @@ -36,6 +38,96 @@ describe('accounts', { tags: '@smoke' }, () => { cy.getByTestId('tab-accounts') .get(tradingAccountRowId) .find('[col-id="deposited"]') - .should('have.text', '1,000.00'); + .should('have.text', '1,001.00'); + }); + describe('sorting by ag-grid columns should work well', () => { + it('sorting by asset', () => { + cy.getByTestId('Collateral').click(); + const marketsSortedDefault = ['tBTC', 'AST0', 'tEURO', 'tDAI', 'tBTC']; + const marketsSortedAsc = ['AST0', 'tBTC', 'tBTC', 'tDAI', 'tEURO']; + const marketsSortedDesc = ['tEURO', 'tDAI', 'tBTC', 'tBTC', 'AST0']; + checkSorting( + 'asset.symbol', + marketsSortedDefault, + marketsSortedAsc, + marketsSortedDesc + ); + }); + + it('sorting by total', () => { + cy.getByTestId('Collateral').click(); + const marketsSortedDefault = [ + '1,000.00002', + '1,001.00', + '1,000.01', + '1,000.01', + '1,000.00001', + ]; + const marketsSortedAsc = [ + '1,000.00001', + '1,000.00002', + '1,000.01', + '1,000.01', + '1,001.00', + ]; + const marketsSortedDesc = [ + '1,001.00', + '1,000.01', + '1,000.01', + '1,000.00002', + '1,000.00001', + ]; + checkSorting( + 'deposited', + marketsSortedDefault, + marketsSortedAsc, + marketsSortedDesc + ); + }); + + it('sorting by used', () => { + cy.getByTestId('Collateral').click(); + const marketsSortedDefault = ['0.00', '1.00', '0.01', '0.01', '0.00']; + const marketsSortedAsc = ['0.00', '0.00', '0.01', '0.01', '1.00']; + const marketsSortedDesc = ['1.00', '0.01', '0.01', '0.00', '0.00']; + checkSorting( + 'used', + marketsSortedDefault, + marketsSortedAsc, + marketsSortedDesc + ); + }); + + it('sorting by available', () => { + cy.getByTestId('Collateral').click(); + const marketsSortedDefault = [ + '1,000.00002', + '1,000.00', + '1,000.00', + '1,000.00', + '1,000.00001', + ]; + const marketsSortedAsc = [ + '1,000.00', + '1,000.00', + '1,000.00', + '1,000.00001', + '1,000.00002', + ]; + const marketsSortedDesc = [ + '1,000.00002', + '1,000.00001', + '1,000.00', + '1,000.00', + '1,000.00', + ]; + + checkSorting( + 'available', + marketsSortedDefault, + marketsSortedAsc, + marketsSortedDesc + ); + }); }); }); diff --git a/apps/trading-e2e/src/integration/trading-positions.cy.ts b/apps/trading-e2e/src/integration/trading-positions.cy.ts index d3af225f8..cecd0732b 100644 --- a/apps/trading-e2e/src/integration/trading-positions.cy.ts +++ b/apps/trading-e2e/src/integration/trading-positions.cy.ts @@ -1,3 +1,4 @@ +import { checkSorting } from '@vegaprotocol/cypress'; import { aliasGQLQuery } from '@vegaprotocol/cypress'; import { marketsDataQuery } from '@vegaprotocol/mock'; @@ -61,6 +62,54 @@ describe('positions', { tags: '@smoke' }, () => { }); }); + describe('sorting by ag-grid columns should work well', () => { + it('sorting by Market', () => { + cy.visit('/#/markets/market-0'); + const marketsSortedDefault = [ + 'ACTIVE MARKET', + 'Apple Monthly (30 Jun 2022)', + ]; + const marketsSortedAsc = ['ACTIVE MARKET', 'Apple Monthly (30 Jun 2022)']; + const marketsSortedDesc = [ + 'Apple Monthly (30 Jun 2022)', + 'ACTIVE MARKET', + ]; + cy.getByTestId('Positions').click(); + checkSorting( + 'marketName', + marketsSortedDefault, + marketsSortedAsc, + marketsSortedDesc + ); + }); + it('sorting by notional', () => { + cy.visit('/#/markets/market-0'); + const marketsSortedDefault = ['276,761.40348', '46,126.90058']; + const marketsSortedAsc = ['46,126.90058', '276,761.40348']; + const marketsSortedDesc = ['276,761.40348', '46,126.90058']; + cy.getByTestId('Positions').click(); + checkSorting( + 'notional', + marketsSortedDefault, + marketsSortedAsc, + marketsSortedDesc + ); + }); + it('sorting by unrealisedPNL', () => { + cy.visit('/#/markets/market-0'); + const marketsSortedDefault = ['8.95', '-0.22519']; + const marketsSortedAsc = ['-0.22519', '8.95']; + const marketsSortedDesc = ['8.95', '-0.22519']; + cy.getByTestId('Positions').click(); + checkSorting( + 'unrealisedPNL', + marketsSortedDefault, + marketsSortedAsc, + marketsSortedDesc + ); + }); + }); + function validatePositionsDisplayed() { cy.getByTestId('tab-positions').should('be.visible'); cy.getByTestId('tab-positions').within(() => { diff --git a/apps/trading-e2e/src/integration/withdraw.cy.ts b/apps/trading-e2e/src/integration/withdraw.cy.ts index abe1458cf..04c416796 100644 --- a/apps/trading-e2e/src/integration/withdraw.cy.ts +++ b/apps/trading-e2e/src/integration/withdraw.cy.ts @@ -66,7 +66,7 @@ describe('withdraw form validation', { tags: '@smoke' }, () => { // 1002-WITH-004 selectAsset(ASSET_SEPOLIA_TBTC); cy.getByTestId(useMaximumAmount).click(); - cy.get(amountField).should('have.value', '1000.00000'); + cy.get(amountField).should('have.value', '1000.00001'); }); }); @@ -102,7 +102,10 @@ describe('withdraw actions', { tags: '@regression' }, () => { 'contain.text', 'Balance available' ); - cy.getByTestId('BALANCE_AVAILABLE_value').should('have.text', '1,000.00'); + cy.getByTestId('BALANCE_AVAILABLE_value').should( + 'have.text', + '1,000.00001' + ); cy.getByTestId('WITHDRAWAL_THRESHOLD_label').should( 'contain.text', 'Delayed withdrawal threshold' diff --git a/libs/accounts/src/lib/accounts-manager.spec.tsx b/libs/accounts/src/lib/accounts-manager.spec.tsx index 8e7cbeb31..d4c0c1e42 100644 --- a/libs/accounts/src/lib/accounts-manager.spec.tsx +++ b/libs/accounts/src/lib/accounts-manager.spec.tsx @@ -1,26 +1,37 @@ -import { act, render, screen, waitFor } from '@testing-library/react'; +import { + act, + getAllByRole, + render, + screen, + waitFor, +} from '@testing-library/react'; import * as helpers from '@vegaprotocol/react-helpers'; -import type { AccountFields } from './accounts-data-provider'; import { AccountManager } from './accounts-manager'; -let mockedUpdate: ({ - delta, - data, -}: { - delta?: never; - data: AccountFields[] | null; -}) => boolean; +const mockedUseDataProvider = jest.fn(); jest.mock('@vegaprotocol/react-helpers', () => ({ ...jest.requireActual('@vegaprotocol/react-helpers'), - useDataProvider: jest.fn((args) => { - mockedUpdate = args.update; - return { - data: [], - }; - }), + useDataProvider: jest.fn(() => mockedUseDataProvider()), })); describe('AccountManager', () => { + beforeEach(() => { + mockedUseDataProvider + .mockImplementationOnce((args) => { + return { + data: [], + }; + }) + .mockImplementationOnce((args) => { + return { + data: [ + { asset: { id: 'a1' }, party: { id: 't1' } }, + { asset: { id: 'a2' }, party: { id: 't2' } }, + ], + }; + }); + }); + it('change partyId should reload data provider', async () => { const { rerender } = render( { }); it('update method should return proper result', async () => { + let rerenderer: (ui: React.ReactElement) => void; await act(() => { - render( + const { rerender } = render( + + ); + rerenderer = rerender; + }); + await waitFor(() => { + expect(screen.getByText('No accounts')).toBeInTheDocument(); + }); + await act(() => { + rerenderer( { /> ); }); - await waitFor(() => { - expect(screen.getByText('No accounts')).toBeInTheDocument(); - }); - await act(() => { - expect(mockedUpdate({ data: [] })).toEqual(true); - expect( - mockedUpdate({ data: [{ party: { id: 't1' } }] as AccountFields[] }) - ).toEqual(false); - expect( - mockedUpdate({ data: [{ party: { id: 't2' } }] as AccountFields[] }) - ).toEqual(true); - expect(mockedUpdate({ data: [] })).toEqual(false); - expect(mockedUpdate({ data: [] })).toEqual(true); + const container = document.querySelector('.ag-center-cols-container'); + await waitFor(() => { + expect(container).toBeInTheDocument(); }); + expect(getAllByRole(container as HTMLDivElement, 'row')).toHaveLength(2); }); }); diff --git a/libs/accounts/src/lib/accounts-manager.tsx b/libs/accounts/src/lib/accounts-manager.tsx index 728f6ea1f..d8c8194a0 100644 --- a/libs/accounts/src/lib/accounts-manager.tsx +++ b/libs/accounts/src/lib/accounts-manager.tsx @@ -1,14 +1,9 @@ -import { - t, - useDataProvider, - updateGridData, -} from '@vegaprotocol/react-helpers'; +import { t, useDataProvider } from '@vegaprotocol/react-helpers'; import { AsyncRenderer } from '@vegaprotocol/ui-toolkit'; import type { AgGridReact } from 'ag-grid-react'; -import { useRef, useMemo, useCallback, memo } from 'react'; +import { useRef, useMemo, memo } from 'react'; import type { AccountFields } from './accounts-data-provider'; import { aggregatedAccountsDataProvider } from './accounts-data-provider'; -import type { GetRowsParams } from './accounts-table'; import { AccountTable } from './accounts-table'; interface AccountManagerProps { @@ -27,40 +22,22 @@ export const AccountManager = ({ isReadOnly, }: AccountManagerProps) => { const gridRef = useRef(null); - const dataRef = useRef(null); const variables = useMemo(() => ({ partyId }), [partyId]); - const update = useCallback( - ({ data }: { data: AccountFields[] | null }) => { - return updateGridData(dataRef, data, gridRef); - }, - [gridRef] - ); const { data, loading, error } = useDataProvider({ dataProvider: aggregatedAccountsDataProvider, - update, variables, }); - const getRows = useCallback( - async ({ successCallback, startRow, endRow }: GetRowsParams) => { - const rowsThisBlock = dataRef.current - ? dataRef.current.slice(startRow, endRow) - : []; - const lastRow = dataRef.current ? dataRef.current.length : 0; - successCallback(rowsThisBlock, lastRow); - }, - [] - ); return (
null} />
{ + checkSortChange(orderTabDefault, column); + cy.get('.ag-header-container').within(() => { + cy.get(`[col-id="${column}"]`).click(); + }); + checkSortChange(orderTabAsc, column); + cy.get('.ag-header-container').within(() => { + cy.get(`[col-id="${column}"]`).click(); + }); + checkSortChange(orderTabDesc, column); +}; +const checkSortChange = (tabsArr: string[], column: string) => { + cy.get('.ag-center-cols-container').within(() => { + tabsArr.forEach((entry, i) => { + cy.get(`[row-index="${i}"]`).within(() => { + cy.get(`[col-id="${column}"]`).should('have.text', tabsArr[i]); + }); + }); + }); +}; diff --git a/libs/fills/src/lib/use-fills-list.spec.ts b/libs/fills/src/lib/use-fills-list.spec.ts index 4c2ae605f..9d539a385 100644 --- a/libs/fills/src/lib/use-fills-list.spec.ts +++ b/libs/fills/src/lib/use-fills-list.spec.ts @@ -28,6 +28,7 @@ describe('useFillsList Hook', () => { current: { api: { refreshInfiniteCache: mockRefreshAgGridApi, + getModel: () => ({ getType: () => 'infinite' }), }, } as unknown as AgGridReact, }; diff --git a/libs/orders/src/lib/components/order-list-manager/use-order-list-data.spec.ts b/libs/orders/src/lib/components/order-list-manager/use-order-list-data.spec.ts index efd1ed44f..ea39ab17a 100644 --- a/libs/orders/src/lib/components/order-list-manager/use-order-list-data.spec.ts +++ b/libs/orders/src/lib/components/order-list-manager/use-order-list-data.spec.ts @@ -34,6 +34,7 @@ describe('useOrderListData Hook', () => { current: { api: { refreshInfiniteCache: mockRefreshAgGridApi, + getModel: () => ({ getType: () => 'infinite' }), }, } as unknown as AgGridReact, }; diff --git a/libs/positions/src/lib/positions-manager.tsx b/libs/positions/src/lib/positions-manager.tsx index 0cdc31d2d..5a3cd7c99 100644 --- a/libs/positions/src/lib/positions-manager.tsx +++ b/libs/positions/src/lib/positions-manager.tsx @@ -18,7 +18,7 @@ export const PositionsManager = ({ isReadOnly, }: PositionsManagerProps) => { const gridRef = useRef(null); - const { data, error, loading, getRows } = usePositionsData(partyId, gridRef); + const { data, error, loading } = usePositionsData(partyId, gridRef, true); const create = useVegaTransactionStore((store) => store.create); const onClose = ({ marketId, @@ -51,9 +51,8 @@ export const PositionsManager = ({ return (
null} diff --git a/libs/positions/src/lib/positions-table.tsx b/libs/positions/src/lib/positions-table.tsx index b9311c44b..05565cde8 100644 --- a/libs/positions/src/lib/positions-table.tsx +++ b/libs/positions/src/lib/positions-table.tsx @@ -142,7 +142,10 @@ export const PositionsTable = forwardRef( }: VegaValueGetterParams) => { return data?.openVolume === undefined ? undefined - : toBigNum(data?.openVolume, data.decimals).toNumber(); + : toBigNum( + data?.openVolume, + data.positionDecimalPlaces + ).toNumber(); }} valueFormatter={({ data, diff --git a/libs/positions/src/lib/use-positions-data.spec.tsx b/libs/positions/src/lib/use-positions-data.spec.tsx index ee40c446c..8de6dcbb2 100644 --- a/libs/positions/src/lib/use-positions-data.spec.tsx +++ b/libs/positions/src/lib/use-positions-data.spec.tsx @@ -69,6 +69,7 @@ describe('usePositionData Hook', () => { api: { refreshInfiniteCache: mockRefreshInfiniteCache, getRowNode: mockGetRowNode, + getModel: () => ({ getType: () => 'infinite' }), }, } as unknown as AgGridReact, }; diff --git a/libs/positions/src/lib/use-positions-data.tsx b/libs/positions/src/lib/use-positions-data.tsx index 805e2341e..313054bb9 100644 --- a/libs/positions/src/lib/use-positions-data.tsx +++ b/libs/positions/src/lib/use-positions-data.tsx @@ -11,7 +11,8 @@ export const getRowId = ({ data }: { data: Position }) => data.marketId; export const usePositionsData = ( partyId: string, - gridRef: RefObject + gridRef: RefObject, + clientSideModel?: boolean ) => { const variables = useMemo( () => ({ partyId }), @@ -20,9 +21,9 @@ export const usePositionsData = ( const dataRef = useRef(null); const update = useCallback( ({ data }: { data: Position[] | null }) => { - return updateGridData(dataRef, data, gridRef); + return clientSideModel ? false : updateGridData(dataRef, data, gridRef); }, - [gridRef] + [gridRef, clientSideModel] ); const { data, error, loading } = useDataProvider({ dataProvider: positionsMetricsProvider, diff --git a/libs/react-helpers/src/lib/ag-grid-update.ts b/libs/react-helpers/src/lib/ag-grid-update.ts index ece98779b..f5c452ffe 100644 --- a/libs/react-helpers/src/lib/ag-grid-update.ts +++ b/libs/react-helpers/src/lib/ag-grid-update.ts @@ -12,7 +12,9 @@ export const updateGridData = ( ) => { const rerender = isXOrWasEmpty(dataRef.current, data); dataRef.current = data; - gridRef.current?.api?.refreshInfiniteCache(); + if (gridRef.current?.api?.getModel().getType() === 'infinite') { + gridRef.current?.api?.refreshInfiniteCache(); + } return !rerender; };