Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e8271b861 | ||
|
|
d0e64364e3 | ||
|
|
737ffb4c35 | ||
|
|
53048ac8ef | ||
|
|
05ca1a09b9 |
@@ -6,7 +6,7 @@ name: 'Add Issues To Project Board'
|
||||
types:
|
||||
- opened
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_NEW_CARD_TO_PROJECT }}
|
||||
GH_TOKEN: ${{ secrets.PROJECT_MANAGE_ACTION }}
|
||||
PROJECT_ID: ${{ secrets.FRONT_END_PROJECT_ID }}
|
||||
ISSUE_ID: ${{ github.event.issue.node_id }}
|
||||
USER: ${{ github.actor }}
|
||||
|
||||
@@ -40,7 +40,7 @@ context.skip('Transactions page', function () {
|
||||
.first()
|
||||
.click({ force: true });
|
||||
} else {
|
||||
cy.slack('Unable to find any transactions on page');
|
||||
cy.log('Unable to find any transactions on page');
|
||||
cy.screenshot();
|
||||
}
|
||||
});
|
||||
@@ -78,7 +78,7 @@ context.skip('Transactions page', function () {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cy.slack('Unable to find any transactions on page');
|
||||
cy.log('Unable to find any transactions on page');
|
||||
cy.screenshot();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ export const PartyBlockStake = ({
|
||||
{p?.stakingSummary.currentStakeAvailable ? (
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow noBorder={true}>
|
||||
<div>{t('Available stake')}</div>
|
||||
<div>{t('Associated to key')}</div>
|
||||
<div>
|
||||
<GovernanceAssetBalance
|
||||
price={p.stakingSummary.currentStakeAvailable}
|
||||
@@ -62,7 +62,7 @@ export const PartyBlockStake = ({
|
||||
</div>
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow noBorder={true}>
|
||||
<div>{t('Active stake')}</div>
|
||||
<div>{t('Staked to validator')}</div>
|
||||
<div>
|
||||
<GovernanceAssetBalance price={linkedStake || '0'} />
|
||||
</div>
|
||||
|
||||
@@ -369,6 +369,10 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
.first()
|
||||
.find('button svg')
|
||||
.should('exist');
|
||||
cy.get(rowSelector)
|
||||
.find('[col-id="successorMarketID"]')
|
||||
.first()
|
||||
.should('have.text', ' - ');
|
||||
});
|
||||
|
||||
// test market list for market in terminated state
|
||||
|
||||
@@ -81,6 +81,12 @@ describe('order book', { tags: '@smoke' }, () => {
|
||||
cy.getByTestId(dealTicketSize).should('have.value', '7');
|
||||
});
|
||||
|
||||
it('copy size to deal ticket form', () => {
|
||||
// 6003-ORDB-009
|
||||
cy.getByTestId(bidVolume).click();
|
||||
cy.getByTestId(dealTicketSize).should('have.value', '1');
|
||||
});
|
||||
|
||||
it('change price resolution', () => {
|
||||
// 6003-ORDB-008
|
||||
const resolutions = [
|
||||
@@ -95,14 +101,13 @@ describe('order book', { tags: '@smoke' }, () => {
|
||||
'1,000',
|
||||
'10,000',
|
||||
];
|
||||
cy.getByTestId(priceResolution).click();
|
||||
cy.get('[role="menu"]')
|
||||
.find('[role="menuitem"]')
|
||||
cy.getByTestId(priceResolution)
|
||||
.find('option')
|
||||
.each(($el, index) => {
|
||||
expect($el.text()).to.equal(resolutions[index]);
|
||||
});
|
||||
|
||||
cy.get('[role="menuitem"]').eq(4).click();
|
||||
cy.getByTestId(priceResolution).select('0.0');
|
||||
cy.getByTestId(resPrice).should('have.text', '99.0');
|
||||
cy.getByTestId(askPrice).should('not.exist');
|
||||
cy.getByTestId(bidPrice).should('not.exist');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { act, render, screen, within } from '@testing-library/react';
|
||||
import { act, render, screen, within, waitFor } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { Closed } from './closed';
|
||||
import { MarketStateMapping, PropertyKeyType } from '@vegaprotocol/types';
|
||||
import { PositionStatus } from '@vegaprotocol/types';
|
||||
@@ -211,15 +212,22 @@ describe('Closed', () => {
|
||||
it('renders correctly formatted and filtered rows', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MockedProvider
|
||||
mocks={[marketsMock, marketsDataMock, positionsMock, oracleDataMock]}
|
||||
>
|
||||
<VegaWalletContext.Provider
|
||||
value={{ pubKey } as VegaWalletContextShape}
|
||||
<MemoryRouter>
|
||||
<MockedProvider
|
||||
mocks={[
|
||||
marketsMock,
|
||||
marketsDataMock,
|
||||
positionsMock,
|
||||
oracleDataMock,
|
||||
]}
|
||||
>
|
||||
<Closed />
|
||||
</VegaWalletContext.Provider>
|
||||
</MockedProvider>
|
||||
<VegaWalletContext.Provider
|
||||
value={{ pubKey } as VegaWalletContextShape}
|
||||
>
|
||||
<Closed />
|
||||
</VegaWalletContext.Provider>
|
||||
</MockedProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
});
|
||||
// screen.debug(document, Infinity);
|
||||
@@ -230,6 +238,7 @@ describe('Closed', () => {
|
||||
'Description',
|
||||
'Status',
|
||||
'Settlement date',
|
||||
'Successor market',
|
||||
'Best bid',
|
||||
'Best offer',
|
||||
'Mark price',
|
||||
@@ -247,6 +256,7 @@ describe('Closed', () => {
|
||||
market.tradableInstrument.instrument.name,
|
||||
MarketStateMapping[market.state],
|
||||
'3 days ago',
|
||||
'-',
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
addDecimalsFormatNumber(marketsData.bestBidPrice, market.decimalPlaces),
|
||||
addDecimalsFormatNumber(
|
||||
@@ -315,20 +325,22 @@ describe('Closed', () => {
|
||||
};
|
||||
await act(async () => {
|
||||
render(
|
||||
<MockedProvider
|
||||
mocks={[
|
||||
mixedMarketsMock,
|
||||
marketsDataMock,
|
||||
positionsMock,
|
||||
oracleDataMock,
|
||||
]}
|
||||
>
|
||||
<VegaWalletContext.Provider
|
||||
value={{ pubKey } as VegaWalletContextShape}
|
||||
<MemoryRouter>
|
||||
<MockedProvider
|
||||
mocks={[
|
||||
mixedMarketsMock,
|
||||
marketsDataMock,
|
||||
positionsMock,
|
||||
oracleDataMock,
|
||||
]}
|
||||
>
|
||||
<Closed />
|
||||
</VegaWalletContext.Provider>
|
||||
</MockedProvider>
|
||||
<VegaWalletContext.Provider
|
||||
value={{ pubKey } as VegaWalletContextShape}
|
||||
>
|
||||
<Closed />
|
||||
</VegaWalletContext.Provider>
|
||||
</MockedProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -359,4 +371,74 @@ describe('Closed', () => {
|
||||
});
|
||||
expect(cells).toEqual(expectedRows.map((m) => m.node.id));
|
||||
});
|
||||
|
||||
it('successor marked should be visible', async () => {
|
||||
const mixedMarkets = [
|
||||
{
|
||||
__typename: 'MarketEdge' as const,
|
||||
node: createMarketFragment({
|
||||
id: 'include-0',
|
||||
state: MarketState.STATE_SETTLED,
|
||||
successorMarketID: 'successorMarketID',
|
||||
}),
|
||||
},
|
||||
{
|
||||
__typename: 'MarketEdge' as const,
|
||||
node: {
|
||||
...createMarketFragment({
|
||||
id: 'successorMarketID',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
...createMarketFragment().tradableInstrument,
|
||||
instrument: {
|
||||
...createMarketFragment().tradableInstrument.instrument,
|
||||
id: 'successorAssset',
|
||||
name: 'Successor Market Name',
|
||||
code: 'SuccessorCode',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const mixedMarketsMock: MockedResponse<MarketsQuery> = {
|
||||
request: {
|
||||
query: MarketsDocument,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
marketsConnection: {
|
||||
__typename: 'MarketConnection',
|
||||
edges: mixedMarkets,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<MockedProvider
|
||||
mocks={[
|
||||
mixedMarketsMock,
|
||||
marketsDataMock,
|
||||
positionsMock,
|
||||
oracleDataMock,
|
||||
]}
|
||||
>
|
||||
<VegaWalletContext.Provider
|
||||
value={{ pubKey } as VegaWalletContextShape}
|
||||
>
|
||||
<Closed />
|
||||
</VegaWalletContext.Provider>
|
||||
</MockedProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.getByRole('button', { name: 'SuccessorCode' })
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,11 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
AgGridLazy as AgGrid,
|
||||
COL_DEFS,
|
||||
MarketNameCell,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { useMemo } from 'react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
|
||||
@@ -20,6 +24,7 @@ import type {
|
||||
import {
|
||||
MarketActionsDropdown,
|
||||
closedMarketsWithDataProvider,
|
||||
marketProvider,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
@@ -27,6 +32,7 @@ import type { ColDef } from 'ag-grid-community';
|
||||
import { SettlementDateCell } from './settlement-date-cell';
|
||||
import { SettlementPriceCell } from './settlement-price-cell';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||
|
||||
type SettlementAsset =
|
||||
MarketMaybeWithData['tradableInstrument']['instrument']['product']['settlementAsset'];
|
||||
@@ -48,6 +54,7 @@ interface Row {
|
||||
tradingTerminationOracleId: string;
|
||||
settlementAsset: SettlementAsset;
|
||||
realisedPNL: string | undefined;
|
||||
successorMarketID: string | undefined | null;
|
||||
}
|
||||
|
||||
export const Closed = () => {
|
||||
@@ -109,6 +116,7 @@ export const Closed = () => {
|
||||
instrument.product.dataSourceSpecForTradingTermination.id,
|
||||
settlementAsset: instrument.product.settlementAsset,
|
||||
realisedPNL: position?.node.realisedPNL,
|
||||
successorMarketID: market.successorMarketID,
|
||||
};
|
||||
|
||||
return row;
|
||||
@@ -120,6 +128,28 @@ export const Closed = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const SuccessorMarketRenderer = ({
|
||||
value,
|
||||
}: VegaICellRendererParams<Row, 'successorMarketID'>) => {
|
||||
const { data } = useDataProvider({
|
||||
dataProvider: marketProvider,
|
||||
variables: {
|
||||
marketId: value || '',
|
||||
},
|
||||
skip: !value,
|
||||
});
|
||||
const onMarketClick = useMarketClickHandler();
|
||||
return data ? (
|
||||
<MarketNameCell
|
||||
value={data.tradableInstrument.instrument.code}
|
||||
data={data}
|
||||
onMarketClick={onMarketClick}
|
||||
/>
|
||||
) : (
|
||||
' - '
|
||||
);
|
||||
};
|
||||
|
||||
const ClosedMarketsDataGrid = ({
|
||||
rowData,
|
||||
error,
|
||||
@@ -199,6 +229,11 @@ const ClosedMarketsDataGrid = ({
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t('Successor market'),
|
||||
field: 'successorMarketID',
|
||||
cellRenderer: 'SuccessorMarketRenderer',
|
||||
},
|
||||
{
|
||||
headerName: t('Best bid'),
|
||||
field: 'bestBidPrice',
|
||||
@@ -311,7 +346,9 @@ const ClosedMarketsDataGrid = ({
|
||||
defaultColDef={{
|
||||
resizable: true,
|
||||
minWidth: 100,
|
||||
flex: 1,
|
||||
}}
|
||||
components={{ SuccessorMarketRenderer }}
|
||||
overlayNoRowsTemplate={error ? error.message : t('No markets')}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@ import { addMockGQLCommand } from './lib/mock-gql';
|
||||
import { addMockSubscription } from './lib/mock-ws';
|
||||
import { addMockWalletCommand } from './lib/mock-rest';
|
||||
import { addMockWeb3ProviderCommand } from './lib/commands/mock-web3-provider';
|
||||
import { addSlackCommand } from './lib/commands/slack';
|
||||
import { addHighlightLog } from './lib/commands/highlight-log';
|
||||
import { addGetAssets } from './lib/commands/get-assets';
|
||||
import { addVegaWalletReceiveFaucetedAsset } from './lib/commands/vega-wallet-receive-fauceted-asset';
|
||||
@@ -26,7 +25,6 @@ import { addVegaWalletTopUpRewardsPool } from './lib/commands/vega-wallet-top-up
|
||||
import { addAssociateTokensToVegaWallet } from './lib/commands/associate-tokens-to-vega-wallet';
|
||||
|
||||
addGetTestIdcommand();
|
||||
addSlackCommand();
|
||||
addMockGQLCommand();
|
||||
addMockSubscription();
|
||||
addMockWalletCommand();
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
namespace Cypress {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface Chainable<Subject> {
|
||||
slack(message: string): void;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function addSlackCommand() {
|
||||
// @ts-ignore - ignoring Cypress type error which gets resolved when Cypress uses the command
|
||||
Cypress.Commands.add('slack', (message) => {
|
||||
const text = `${message}: ${JSON.stringify(Cypress.spec)}`;
|
||||
|
||||
cy.log('NOTIFYING SLACK');
|
||||
|
||||
const webhook = Cypress.env('SLACK_WEBHOOK');
|
||||
|
||||
if (!webhook) {
|
||||
return;
|
||||
}
|
||||
|
||||
cy.request('POST', webhook, {
|
||||
text,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -13,12 +13,8 @@ interface OrderbookRowProps {
|
||||
price: string;
|
||||
onClick?: (args: { price?: string; size?: string }) => void;
|
||||
type: VolumeType;
|
||||
width: number;
|
||||
}
|
||||
|
||||
const HIDE_VOL_WIDTH = 150;
|
||||
const HIDE_CUMULATIVE_VOL_WIDTH = 220;
|
||||
|
||||
const CumulationBar = ({
|
||||
cumulativeValue = 0,
|
||||
type,
|
||||
@@ -30,7 +26,7 @@ const CumulationBar = ({
|
||||
<div
|
||||
data-testid={`${VolumeType.bid === type ? 'bid' : 'ask'}-bar`}
|
||||
className={classNames(
|
||||
'absolute top-0 left-0 h-full',
|
||||
'absolute top-0 left-0 h-full transition-all',
|
||||
type === VolumeType.bid
|
||||
? 'bg-market-green-300 dark:bg-market-green/50'
|
||||
: 'bg-market-red-300 dark:bg-market-red/30'
|
||||
@@ -94,18 +90,12 @@ export const OrderbookRow = React.memo(
|
||||
price,
|
||||
onClick,
|
||||
type,
|
||||
width,
|
||||
}: OrderbookRowProps) => {
|
||||
const txtId = type === VolumeType.bid ? 'bid' : 'ask';
|
||||
const cols =
|
||||
width >= HIDE_CUMULATIVE_VOL_WIDTH ? 3 : width >= HIDE_VOL_WIDTH ? 2 : 1;
|
||||
return (
|
||||
<div className="relative pr-1">
|
||||
<div className="relative">
|
||||
<CumulationBar cumulativeValue={cumulativeRelativeValue} type={type} />
|
||||
<div
|
||||
data-testid={`${txtId}-rows-container`}
|
||||
className={classNames('grid gap-1 text-right', `grid-cols-${cols}`)}
|
||||
>
|
||||
<div className="grid gap-1 text-right grid-cols-3">
|
||||
<PriceCell
|
||||
testId={`price-${price}`}
|
||||
value={BigInt(price)}
|
||||
@@ -119,30 +109,33 @@ export const OrderbookRow = React.memo(
|
||||
: 'text-market-green-600 dark:text-market-green'
|
||||
}
|
||||
/>
|
||||
{width >= HIDE_VOL_WIDTH && (
|
||||
<NumericCell
|
||||
testId={`${txtId}-vol-${price}`}
|
||||
value={value}
|
||||
valueFormatted={addDecimalsFixedFormatNumber(
|
||||
value,
|
||||
positionDecimalPlaces
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{width >= HIDE_CUMULATIVE_VOL_WIDTH && (
|
||||
<CumulativeVol
|
||||
testId={`cumulative-vol-${price}`}
|
||||
onClick={() =>
|
||||
onClick &&
|
||||
cumulativeValue &&
|
||||
onClick({
|
||||
size: addDecimal(cumulativeValue, positionDecimalPlaces),
|
||||
})
|
||||
}
|
||||
positionDecimalPlaces={positionDecimalPlaces}
|
||||
cumulativeValue={cumulativeValue}
|
||||
/>
|
||||
)}
|
||||
<PriceCell
|
||||
testId={`${txtId}-vol-${price}`}
|
||||
onClick={(value) =>
|
||||
onClick &&
|
||||
value &&
|
||||
onClick({
|
||||
size: addDecimal(value, positionDecimalPlaces),
|
||||
})
|
||||
}
|
||||
value={value}
|
||||
valueFormatted={addDecimalsFixedFormatNumber(
|
||||
value,
|
||||
positionDecimalPlaces
|
||||
)}
|
||||
/>
|
||||
<CumulativeVol
|
||||
testId={`cumulative-vol-${price}`}
|
||||
onClick={() =>
|
||||
onClick &&
|
||||
cumulativeValue &&
|
||||
onClick({
|
||||
size: addDecimal(cumulativeValue, positionDecimalPlaces),
|
||||
})
|
||||
}
|
||||
positionDecimalPlaces={positionDecimalPlaces}
|
||||
cumulativeValue={cumulativeValue}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { render, waitFor, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { render, fireEvent, waitFor, screen } from '@testing-library/react';
|
||||
import { generateMockData, VolumeType } from './orderbook-data';
|
||||
import { Orderbook } from './orderbook';
|
||||
import * as orderbookData from './orderbook-data';
|
||||
@@ -34,7 +33,6 @@ describe('Orderbook', () => {
|
||||
const decimalPlaces = 3;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockOffsetSize(800, 768);
|
||||
});
|
||||
it('markPrice should be in the middle', async () => {
|
||||
@@ -71,17 +69,12 @@ describe('Orderbook', () => {
|
||||
await screen.findByTestId(`middle-mark-price-${params.midPrice}`)
|
||||
).toBeInTheDocument();
|
||||
// Before resolution change the price is 122.934
|
||||
await userEvent.click(await screen.getByTestId('price-122901'));
|
||||
await fireEvent.click(await screen.getByTestId('price-122901'));
|
||||
expect(onClickSpy).toBeCalledWith({ price: '122.901' });
|
||||
|
||||
await userEvent.click(screen.getByTestId('resolution'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
await userEvent.click(screen.getAllByRole('menuitem')[1]);
|
||||
|
||||
const resolutionSelect = screen.getByTestId(
|
||||
'resolution'
|
||||
) as HTMLSelectElement;
|
||||
await fireEvent.change(resolutionSelect, { target: { value: '10' } });
|
||||
expect(orderbookData.compactRows).toHaveBeenCalledWith(
|
||||
mockedData.bids,
|
||||
VolumeType.bid,
|
||||
@@ -92,88 +85,7 @@ describe('Orderbook', () => {
|
||||
VolumeType.ask,
|
||||
10
|
||||
);
|
||||
await userEvent.click(await screen.getByTestId('price-12294'));
|
||||
await fireEvent.click(await screen.getByTestId('price-12294'));
|
||||
expect(onClickSpy).toBeCalledWith({ price: '122.94' });
|
||||
});
|
||||
|
||||
it('plus - minus buttons should change resolution', async () => {
|
||||
const onClickSpy = jest.fn();
|
||||
jest.spyOn(orderbookData, 'compactRows');
|
||||
const mockedData = generateMockData(params);
|
||||
render(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
onClick={onClickSpy}
|
||||
{...mockedData}
|
||||
assetSymbol="USD"
|
||||
/>
|
||||
);
|
||||
expect((orderbookData.compactRows as jest.Mock).mock.lastCall[2]).toEqual(
|
||||
1
|
||||
);
|
||||
expect(screen.getByTestId('minus-button')).toBeDisabled();
|
||||
userEvent.click(screen.getByTestId('plus-button'));
|
||||
await waitFor(() => {
|
||||
expect((orderbookData.compactRows as jest.Mock).mock.lastCall[2]).toEqual(
|
||||
10
|
||||
);
|
||||
});
|
||||
expect(screen.getByTestId('minus-button')).not.toBeDisabled();
|
||||
userEvent.click(screen.getByTestId('minus-button'));
|
||||
await waitFor(() => {
|
||||
expect((orderbookData.compactRows as jest.Mock).mock.lastCall[2]).toEqual(
|
||||
1
|
||||
);
|
||||
});
|
||||
expect(screen.getByTestId('minus-button')).toBeDisabled();
|
||||
await userEvent.click(screen.getByTestId('resolution'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||
});
|
||||
await userEvent.click(screen.getAllByRole('menuitem')[5]);
|
||||
await waitFor(() => {
|
||||
expect((orderbookData.compactRows as jest.Mock).mock.lastCall[2]).toEqual(
|
||||
100000
|
||||
);
|
||||
});
|
||||
expect(screen.getByTestId('plus-button')).toBeDisabled();
|
||||
});
|
||||
|
||||
it('two columns', () => {
|
||||
mockOffsetSize(200, 768);
|
||||
const onClickSpy = jest.fn();
|
||||
const mockedData = generateMockData(params);
|
||||
render(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
onClick={onClickSpy}
|
||||
{...mockedData}
|
||||
assetSymbol="USD"
|
||||
/>
|
||||
);
|
||||
screen.getAllByTestId('bid-rows-container').forEach((item) => {
|
||||
expect(item).toHaveClass('grid-cols-2');
|
||||
});
|
||||
});
|
||||
|
||||
it('one column', () => {
|
||||
mockOffsetSize(140, 768);
|
||||
const onClickSpy = jest.fn();
|
||||
const mockedData = generateMockData(params);
|
||||
render(
|
||||
<Orderbook
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={0}
|
||||
onClick={onClickSpy}
|
||||
{...mockedData}
|
||||
assetSymbol="USD"
|
||||
/>
|
||||
);
|
||||
screen.getAllByTestId('ask-rows-container').forEach((item) => {
|
||||
expect(item).toHaveClass('grid-cols-1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,20 +5,10 @@ import {
|
||||
formatNumberFixed,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { usePrevious } from '@vegaprotocol/react-helpers';
|
||||
import { OrderbookRow } from './orderbook-row';
|
||||
import type { OrderbookRowData } from './orderbook-data';
|
||||
import { compactRows, VolumeType } from './orderbook-data';
|
||||
import {
|
||||
Splash,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
Button,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import classNames from 'classnames';
|
||||
import { useState } from 'react';
|
||||
import type { PriceLevelFieldsFragment } from './__generated__/MarketDepth';
|
||||
@@ -36,7 +26,6 @@ const OrderbookTable = ({
|
||||
decimalPlaces,
|
||||
positionDecimalPlaces,
|
||||
onClick,
|
||||
width,
|
||||
}: {
|
||||
rows: OrderbookRowData[];
|
||||
resolution: number;
|
||||
@@ -44,7 +33,6 @@ const OrderbookTable = ({
|
||||
positionDecimalPlaces: number;
|
||||
type: VolumeType;
|
||||
onClick?: (args: { price?: string; size?: string }) => void;
|
||||
width: number;
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
@@ -71,7 +59,6 @@ const OrderbookTable = ({
|
||||
cumulativeValue={data.cumulativeVol.value}
|
||||
cumulativeRelativeValue={data.cumulativeVol.relativeValue}
|
||||
type={type}
|
||||
width={width}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -112,59 +99,12 @@ export const Orderbook = ({
|
||||
const groupedBids = useMemo(() => {
|
||||
return compactRows(bids, VolumeType.bid, resolution);
|
||||
}, [bids, resolution]);
|
||||
const [isOpen, setOpen] = useState(false);
|
||||
const previousMidPrice = usePrevious(midPrice);
|
||||
const icon =
|
||||
midPrice && previousMidPrice !== midPrice ? (
|
||||
<span
|
||||
className={classNames(
|
||||
(previousMidPrice || '') > midPrice
|
||||
? 'text-market-red dark:text-market-red'
|
||||
: 'text-market-green-600 dark:text-market-green'
|
||||
)}
|
||||
>
|
||||
<VegaIcon
|
||||
name={
|
||||
(previousMidPrice || '') > midPrice
|
||||
? VegaIconNames.ARROW_DOWN
|
||||
: VegaIconNames.ARROW_UP
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-vega-blue-500 dark:text-vega-blue-500">
|
||||
<VegaIcon name={VegaIconNames.BULLET} />
|
||||
</span>
|
||||
);
|
||||
|
||||
const formatResolution = (r: number) => {
|
||||
return formatNumberFixed(
|
||||
Math.log10(r) - decimalPlaces > 0
|
||||
? Math.pow(10, Math.log10(r) - decimalPlaces)
|
||||
: 0,
|
||||
decimalPlaces - Math.log10(r)
|
||||
);
|
||||
};
|
||||
|
||||
const increaseResolution = () => {
|
||||
const index = resolutions.indexOf(resolution);
|
||||
if (index < resolutions.length - 1) {
|
||||
setResolution(resolutions[index + 1]);
|
||||
}
|
||||
};
|
||||
|
||||
const decreaseResolution = () => {
|
||||
const index = resolutions.indexOf(resolution);
|
||||
if (index > 0) {
|
||||
setResolution(resolutions[index - 1]);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-full pl-1 text-xs grid grid-rows-[1fr_min-content]">
|
||||
<div>
|
||||
<ReactVirtualizedAutoSizer>
|
||||
{({ width, height }) => {
|
||||
<ReactVirtualizedAutoSizer disableWidth>
|
||||
{({ height }) => {
|
||||
const limit = Math.max(
|
||||
1,
|
||||
Math.floor((height - midHeight) / 2 / (rowHeight + rowGap))
|
||||
@@ -176,7 +116,6 @@ export const Orderbook = ({
|
||||
className="overflow-hidden grid"
|
||||
data-testid="orderbook-grid-element"
|
||||
style={{
|
||||
width: width + 'px',
|
||||
height: height + 'px',
|
||||
gridTemplateRows: `1fr ${midHeight}px 1fr`, // cannot use tailwind here as tailwind will not parse a class string with interpolation
|
||||
}}
|
||||
@@ -190,7 +129,6 @@ export const Orderbook = ({
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={positionDecimalPlaces}
|
||||
onClick={onClick}
|
||||
width={width}
|
||||
/>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
{midPrice && (
|
||||
@@ -202,7 +140,6 @@ export const Orderbook = ({
|
||||
{addDecimalsFormatNumber(midPrice, decimalPlaces)}
|
||||
</span>
|
||||
<span className="text-base">{assetSymbol}</span>
|
||||
{icon}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -213,7 +150,6 @@ export const Orderbook = ({
|
||||
decimalPlaces={decimalPlaces}
|
||||
positionDecimalPlaces={positionDecimalPlaces}
|
||||
onClick={onClick}
|
||||
width={width}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
@@ -226,61 +162,26 @@ export const Orderbook = ({
|
||||
}}
|
||||
</ReactVirtualizedAutoSizer>
|
||||
</div>
|
||||
<div className="border-t border-default flex">
|
||||
<Button
|
||||
onClick={increaseResolution}
|
||||
size="xs"
|
||||
disabled={resolutions.indexOf(resolution) >= resolutions.length - 1}
|
||||
className="text-black dark:text-white rounded-none border-y-0 border-l-0 flex items-center border-r-1"
|
||||
data-testid="plus-button"
|
||||
<div className="border-t border-default">
|
||||
<select
|
||||
onChange={(e) => {
|
||||
setResolution(Number(e.currentTarget.value));
|
||||
}}
|
||||
value={resolution}
|
||||
className="block bg-neutral-100 dark:bg-neutral-700 font-mono text-right"
|
||||
data-testid="resolution"
|
||||
>
|
||||
<VegaIcon size={12} name={VegaIconNames.PLUS} />
|
||||
</Button>
|
||||
<DropdownMenu
|
||||
open={isOpen}
|
||||
onOpenChange={(open) => setOpen(open)}
|
||||
trigger={
|
||||
<DropdownMenuTrigger
|
||||
data-testid="resolution"
|
||||
className="flex justify-between px-1 items-center"
|
||||
style={{
|
||||
width: `${
|
||||
Math.max.apply(
|
||||
null,
|
||||
resolutions.map((item) => formatResolution(item).length)
|
||||
) + 3
|
||||
}ch`,
|
||||
}}
|
||||
>
|
||||
<VegaIcon
|
||||
size={12}
|
||||
name={
|
||||
isOpen ? VegaIconNames.CHEVRON_UP : VegaIconNames.CHEVRON_DOWN
|
||||
}
|
||||
/>
|
||||
<div className="text-xs text-left">
|
||||
{formatResolution(resolution)}
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
}
|
||||
>
|
||||
<DropdownMenuContent align="start">
|
||||
{resolutions.map((r) => (
|
||||
<DropdownMenuItem key={r} onClick={() => setResolution(r)}>
|
||||
{formatResolution(r)}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Button
|
||||
onClick={decreaseResolution}
|
||||
size="xs"
|
||||
disabled={resolutions.indexOf(resolution) <= 0}
|
||||
className="text-black dark:text-white rounded-none border-y-0 border-l-1 flex items-center"
|
||||
data-testid="minus-button"
|
||||
>
|
||||
<VegaIcon size={12} name={VegaIconNames.MINUS} />
|
||||
</Button>
|
||||
{resolutions.map((r) => (
|
||||
<option key={r} value={r}>
|
||||
{formatNumberFixed(
|
||||
Math.log10(r) - decimalPlaces > 0
|
||||
? Math.pow(10, Math.log10(r) - decimalPlaces)
|
||||
: 0,
|
||||
decimalPlaces - Math.log10(r)
|
||||
)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -141,6 +141,7 @@ export const createMarketFragment = (
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
successorMarketID: null,
|
||||
__typename: 'Market',
|
||||
};
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
export const IconArrowUp = ({ size = 16 }: { size: number }) => {
|
||||
return (
|
||||
<svg width={size} height={size} viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M 7.47,3.63
|
||||
C 7.47,3.63 2.37,8.72 2.37,8.72
|
||||
2.37,8.72 1.63,7.98 1.63,7.98
|
||||
1.63,7.98 8.00,1.60 8.00,1.60
|
||||
8.00,1.60 14.37,7.98 14.37,7.98
|
||||
14.37,7.98 13.63,8.72 13.63,8.72
|
||||
13.63,8.72 8.53,3.63 8.53,3.63
|
||||
8.53,3.63 8.53,14.35 8.53,14.35
|
||||
8.53,14.35 7.47,14.35 7.47,14.35
|
||||
7.47,14.35 7.47,3.63 7.47,3.63 Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
export const IconBullet = ({ size = 16 }: { size: number }) => {
|
||||
return (
|
||||
<svg width={size} height={size} viewBox="0 0 16 16">
|
||||
<circle cx="8" cy="8" r="6" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
export const IconMinus = ({ size = 16 }: { size: number }) => {
|
||||
return (
|
||||
<svg width={size} height={size} viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M 0.92,8.58
|
||||
C 0.92,8.58 0.92,7.48 0.92,7.48
|
||||
0.92,7.48 15.01,7.48 15.01,7.48
|
||||
15.01,7.48 15.01,8.58 15.01,8.58
|
||||
15.01,8.58 0.92,8.58 0.92,8.58 Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
export const IconPlus = ({ size = 16 }: { size: number }) => {
|
||||
return (
|
||||
<svg width={size} height={size} viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M 7.43,15.24
|
||||
C 7.43,15.24 7.43,8.58 7.43,8.58
|
||||
7.43,8.58 0.92,8.58 0.92,8.58
|
||||
0.92,8.58 0.92,7.48 0.92,7.48
|
||||
0.92,7.48 7.43,7.48 7.43,7.48
|
||||
7.43,7.48 7.43,0.85 7.43,0.85
|
||||
7.43,0.85 8.48,0.85 8.48,0.85
|
||||
8.48,0.85 8.48,7.48 8.48,7.48
|
||||
8.48,7.48 15.01,7.48 15.01,7.48
|
||||
15.01,7.48 15.01,8.58 15.01,8.58
|
||||
15.01,8.58 8.48,8.58 8.48,8.58
|
||||
8.48,8.58 8.48,15.24 8.48,15.24
|
||||
8.48,15.24 7.43,15.24 7.43,15.24 Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -1,8 +1,6 @@
|
||||
import { IconArrowDown } from './svg-icons/icon-arrow-down';
|
||||
import { IconArrowUp } from './svg-icons/icon-arrow-up';
|
||||
import { IconArrowRight } from './svg-icons/icon-arrow-right';
|
||||
import { IconBreakdown } from './svg-icons/icon-breakdown';
|
||||
import { IconBullet } from './svg-icons/icon-bullet';
|
||||
import { IconChevronDown } from './svg-icons/icon-chevron-down';
|
||||
import { IconChevronLeft } from './svg-icons/icon-chevron-left';
|
||||
import { IconChevronUp } from './svg-icons/icon-chevron-up';
|
||||
@@ -15,11 +13,9 @@ import { IconGlobe } from './svg-icons/icon-globe';
|
||||
import { IconInfo } from './svg-icons/icon-info';
|
||||
import { IconKebab } from './svg-icons/icon-kebab';
|
||||
import { IconLinkedIn } from './svg-icons/icon-linkedin';
|
||||
import { IconMinus } from './svg-icons/icon-minus';
|
||||
import { IconMoon } from './svg-icons/icon-moon';
|
||||
import { IconOpenExternal } from './svg-icons/icon-open-external';
|
||||
import { IconQuestionMark } from './svg-icons/icon-question-mark';
|
||||
import { IconPlus } from './svg-icons/icon-plus';
|
||||
import { IconTick } from './svg-icons/icon-tick';
|
||||
import { IconTransfer } from './svg-icons/icon-transfer';
|
||||
import { IconTrendUp } from './svg-icons/icon-trend-up';
|
||||
@@ -28,10 +24,8 @@ import { IconWithdraw } from './svg-icons/icon-withdraw';
|
||||
|
||||
export enum VegaIconNames {
|
||||
ARROW_DOWN = 'arrow-down',
|
||||
ARROW_UP = 'arrow-up',
|
||||
ARROW_RIGHT = 'arrow-right',
|
||||
BREAKDOWN = 'breakdown',
|
||||
BULLET = 'bullet',
|
||||
CHEVRON_DOWN = 'chevron-down',
|
||||
CHEVRON_LEFT = 'chevron-left',
|
||||
CHEVRON_UP = 'chevron-up',
|
||||
@@ -44,11 +38,9 @@ export enum VegaIconNames {
|
||||
INFO = 'info',
|
||||
KEBAB = 'kebab',
|
||||
LINKEDIN = 'linkedin',
|
||||
MINUS = 'minus',
|
||||
MOON = 'moon',
|
||||
OPEN_EXTERNAL = 'open-external',
|
||||
QUESTION_MARK = 'question-mark',
|
||||
PLUS = 'plus',
|
||||
TICK = 'tick',
|
||||
TRANSFER = 'transfer',
|
||||
TREND_UP = 'trend-up',
|
||||
@@ -61,7 +53,6 @@ export const VegaIconNameMap: Record<
|
||||
({ size }: { size: number }) => JSX.Element
|
||||
> = {
|
||||
'arrow-down': IconArrowDown,
|
||||
'arrow-up': IconArrowUp,
|
||||
'arrow-right': IconArrowRight,
|
||||
'chevron-down': IconChevronDown,
|
||||
'chevron-left': IconChevronLeft,
|
||||
@@ -70,7 +61,6 @@ export const VegaIconNameMap: Record<
|
||||
'question-mark': IconQuestionMark,
|
||||
'trend-up': IconTrendUp,
|
||||
breakdown: IconBreakdown,
|
||||
bullet: IconBullet,
|
||||
copy: IconCopy,
|
||||
cross: IconCross,
|
||||
deposit: IconDeposit,
|
||||
@@ -80,9 +70,7 @@ export const VegaIconNameMap: Record<
|
||||
info: IconInfo,
|
||||
kebab: IconKebab,
|
||||
linkedin: IconLinkedIn,
|
||||
minus: IconMinus,
|
||||
moon: IconMoon,
|
||||
plus: IconPlus,
|
||||
tick: IconTick,
|
||||
transfer: IconTransfer,
|
||||
twitter: IconTwitter,
|
||||
|
||||
@@ -23,7 +23,6 @@ export const Tabs = ({
|
||||
}
|
||||
return children[0].props.id;
|
||||
});
|
||||
|
||||
return (
|
||||
<TabsPrimitive.Root
|
||||
{...props}
|
||||
@@ -31,7 +30,7 @@ export const Tabs = ({
|
||||
onValueChange={onValueChange || setActiveTab}
|
||||
className="h-full grid grid-rows-[min-content_1fr]"
|
||||
>
|
||||
<div className="border-b border-default min-w-0">
|
||||
<div className="border-b border-default">
|
||||
<TabsPrimitive.List
|
||||
className="flex flex-nowrap overflow-visible"
|
||||
role="tablist"
|
||||
|
||||
Reference in New Issue
Block a user