From 4b3b5c322a7e1b114773cd8631fd3dbc019936dc Mon Sep 17 00:00:00 2001 From: "m.ray" <16125548+MadalinaRaicu@users.noreply.github.com> Date: Fri, 27 Jan 2023 13:55:20 -0500 Subject: [PATCH] fix: trades grid colors (#2766) --- libs/trades/src/lib/Trades.graphql | 2 + libs/trades/src/lib/__generated__/Trades.ts | 8 +- libs/trades/src/lib/trades-table.spec.tsx | 107 ++++++++++---------- libs/trades/src/lib/trades-table.tsx | 36 +++---- libs/trades/src/lib/trades.mock.ts | 5 + 5 files changed, 79 insertions(+), 79 deletions(-) diff --git a/libs/trades/src/lib/Trades.graphql b/libs/trades/src/lib/Trades.graphql index 4bc085283..232939b9d 100644 --- a/libs/trades/src/lib/Trades.graphql +++ b/libs/trades/src/lib/Trades.graphql @@ -3,6 +3,7 @@ fragment TradeFields on Trade { price size createdAt + aggressor market { id } @@ -35,5 +36,6 @@ subscription TradesUpdate($marketId: ID!) { size createdAt marketId + aggressor } } diff --git a/libs/trades/src/lib/__generated__/Trades.ts b/libs/trades/src/lib/__generated__/Trades.ts index a6613eba9..2aa1d880b 100644 --- a/libs/trades/src/lib/__generated__/Trades.ts +++ b/libs/trades/src/lib/__generated__/Trades.ts @@ -3,7 +3,7 @@ import * as Types from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; -export type TradeFieldsFragment = { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, market: { __typename?: 'Market', id: string } }; +export type TradeFieldsFragment = { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, market: { __typename?: 'Market', id: string } }; export type TradesQueryVariables = Types.Exact<{ marketId: Types.Scalars['ID']; @@ -11,14 +11,14 @@ export type TradesQueryVariables = Types.Exact<{ }>; -export type TradesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, tradesConnection?: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, market: { __typename?: 'Market', id: string } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } | null } | null }; +export type TradesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, tradesConnection?: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, market: { __typename?: 'Market', id: string } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } | null } | null }; export type TradesUpdateSubscriptionVariables = Types.Exact<{ marketId: Types.Scalars['ID']; }>; -export type TradesUpdateSubscription = { __typename?: 'Subscription', trades?: Array<{ __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string }> | null }; +export type TradesUpdateSubscription = { __typename?: 'Subscription', trades?: Array<{ __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string, aggressor: Types.Side }> | null }; export const TradeFieldsFragmentDoc = gql` fragment TradeFields on Trade { @@ -26,6 +26,7 @@ export const TradeFieldsFragmentDoc = gql` price size createdAt + aggressor market { id } @@ -89,6 +90,7 @@ export const TradesUpdateDocument = gql` size createdAt marketId + aggressor } } `; diff --git a/libs/trades/src/lib/trades-table.spec.tsx b/libs/trades/src/lib/trades-table.spec.tsx index 849b52608..b50f61271 100644 --- a/libs/trades/src/lib/trades-table.spec.tsx +++ b/libs/trades/src/lib/trades-table.spec.tsx @@ -1,13 +1,15 @@ import { act, render, screen } from '@testing-library/react'; import { getDateTimeFormat } from '@vegaprotocol/react-helpers'; -import { DOWN_CLASS, TradesTable, UP_CLASS } from './trades-table'; +import { SELL_CLASS, TradesTable, BUY_CLASS } from './trades-table'; import type { Trade } from './trades-data-provider'; +import { Side } from '@vegaprotocol/types'; const trade: Trade = { __typename: 'Trade', id: 'trade-id', price: '111122200', size: '2000', + aggressor: Side.SIDE_BUY, createdAt: new Date('2022-04-06T19:00:00').toISOString(), market: { __typename: 'Market', @@ -17,59 +19,58 @@ const trade: Trade = { } as Trade['market'], }; -it('Correct columns are rendered', async () => { - await act(async () => { - render(); - }); - const expectedHeaders = ['Price', 'Size', 'Created at']; - const headers = screen.getAllByRole('columnheader'); - expect(headers).toHaveLength(expectedHeaders.length); - expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders); -}); - -it('Number and data columns are formatted', async () => { - await act(async () => { - render(); +describe('TradesTable', () => { + it('should render correct columns', async () => { + await act(async () => { + render(); + }); + const expectedHeaders = ['Price', 'Size', 'Created at']; + const headers = screen.getAllByRole('columnheader'); + expect(headers).toHaveLength(expectedHeaders.length); + expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders); }); - const cells = screen.getAllByRole('gridcell'); - const expectedValues = [ - '1,111,222.00', - '20.00', - getDateTimeFormat().format(new Date(trade.createdAt)), - ]; - cells.forEach((cell, i) => { - expect(cell).toHaveTextContent(expectedValues[i]); + it('should format number and data columns', async () => { + await act(async () => { + render(); + }); + + const cells = screen.getAllByRole('gridcell'); + const expectedValues = [ + '1,111,222.00', + '20.00', + getDateTimeFormat().format(new Date(trade.createdAt)), + ]; + cells.forEach((cell, i) => { + expect(cell).toHaveTextContent(expectedValues[i]); + }); + }); + + it('should format price and size columns', async () => { + const trade2 = { + ...trade, + id: 'trade-id-2', + price: (Number(trade.price) + 10).toString(), + size: (Number(trade.size) - 10).toString(), + }; + await act(async () => { + render(); + }); + + const cells = screen.getAllByRole('gridcell'); + + const priceCells = cells.filter( + (cell) => cell.getAttribute('col-id') === 'price' + ); + const sizeCells = cells.filter( + (cell) => cell.getAttribute('col-id') === 'size' + ); + + // For first trade price should have green class + // row 1 + expect(priceCells[0]).toHaveClass(BUY_CLASS); + expect(priceCells[1]).not.toHaveClass(SELL_CLASS); + expect(sizeCells[1]).not.toHaveClass(SELL_CLASS); + expect(sizeCells[1]).not.toHaveClass(BUY_CLASS); }); }); - -it('Price and size columns are formatted', async () => { - const trade2 = { - ...trade, - id: 'trade-id-2', - price: (Number(trade.price) + 10).toString(), - size: (Number(trade.size) - 10).toString(), - }; - await act(async () => { - render(); - }); - - const cells = screen.getAllByRole('gridcell'); - - const priceCells = cells.filter( - (cell) => cell.getAttribute('col-id') === 'price' - ); - const sizeCells = cells.filter( - (cell) => cell.getAttribute('col-id') === 'size' - ); - - // For first trade price should have green class and size should have red class - // row 1 - expect(priceCells[0]).toHaveClass(UP_CLASS); - expect(priceCells[1]).not.toHaveClass(DOWN_CLASS); - expect(priceCells[1]).not.toHaveClass(UP_CLASS); - - expect(sizeCells[0]).toHaveClass(DOWN_CLASS); - expect(sizeCells[1]).not.toHaveClass(DOWN_CLASS); - expect(sizeCells[1]).not.toHaveClass(UP_CLASS); -}); diff --git a/libs/trades/src/lib/trades-table.tsx b/libs/trades/src/lib/trades-table.tsx index 2d911297d..97a61ad1a 100644 --- a/libs/trades/src/lib/trades-table.tsx +++ b/libs/trades/src/lib/trades-table.tsx @@ -13,31 +13,22 @@ import type { IDatasource, IGetRowsParams } from 'ag-grid-community'; import type { CellClassParams, ValueFormatterParams } from 'ag-grid-community'; import type { AgGridReactProps } from 'ag-grid-react'; import type { Trade } from './trades-data-provider'; -import BigNumber from 'bignumber.js'; +import { Side } from '@vegaprotocol/types'; -export const UP_CLASS = 'text-vega-green dark:text-vega-green'; -export const DOWN_CLASS = 'text-vega-pink dark:text-vega-pink'; +export const BUY_CLASS = 'text-vega-green dark:text-vega-green'; +export const SELL_CLASS = 'text-vega-pink dark:text-vega-pink'; -const changeCellClass = - (dataKey: string) => - ({ api, value, node }: CellClassParams) => { - const rowIndex = node?.rowIndex; - let colorClass = ''; +const changeCellClass = ({ node }: CellClassParams) => { + let colorClass = ''; - if (typeof rowIndex === 'number') { - const prevRowNode = api.getModel().getRow(rowIndex + 1); - const prevValue = prevRowNode?.data && prevRowNode.data[dataKey]; - const valueNum = new BigNumber(value); + if (node.data?.aggressor === Side.SIDE_BUY) { + colorClass = BUY_CLASS; + } else if (node.data?.aggressor === Side.SIDE_SELL) { + colorClass = SELL_CLASS; + } - if (valueNum.isGreaterThan(prevValue)) { - colorClass = UP_CLASS; - } else if (valueNum.isLessThan(prevValue)) { - colorClass = DOWN_CLASS; - } - } - - return ['font-mono text-right', colorClass].join(' '); - }; + return ['font-mono text-right', colorClass].join(' '); +}; export interface GetRowsParams extends Omit { successCallback(rowsThisBlock: (Trade | null)[], lastRow?: number): void; @@ -77,7 +68,7 @@ export const TradesTable = forwardRef((props, ref) => { field="price" type="rightAligned" width={130} - cellClass={changeCellClass('price')} + cellClass={changeCellClass} valueFormatter={({ value, data, @@ -127,7 +118,6 @@ export const TradesTable = forwardRef((props, ref) => { } return addDecimal(value, data.market.positionDecimalPlaces); }} - cellClass={changeCellClass('size')} />