chore: misc quick wins (#1596)

* fix: make sparkline appear after change cell

* fix: make price come after expiry in market header

* fix: refer to size rather than amount in validation

* fix: radio colors in light theme

* fix: remove orange border from vega tx pending state

* chore: combine deposit and withdraw buttons into single cell

* chore: update accounts table test, remove console warning from breakdown tests

* chore: update order validation test

* chore: place market table header in correct position

* chore: use actual change id to avoid clash

* fix: remove assertion in fills table that is flakey

* chore: render fills table with act

* fix: add a wait time for infura queries to resolve
This commit is contained in:
Matthew Russell 2022-10-04 21:00:06 -07:00 committed by GitHub
parent 61721e61f6
commit 1f8f54617b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 119 additions and 118 deletions

View File

@ -25,7 +25,10 @@ before(() => {
// Mock chainId fetch which happens on every page for wallet connection
cy.mockGQL((req) => {
aliasQuery(req, 'ChainId', {
statistics: { __typename: 'Statistics', chainId: 'test-chain-id' },
statistics: {
__typename: 'Statistics',
chainId: 'vega-fairground-202210041151',
},
});
});
});

View File

@ -24,7 +24,10 @@ before(() => {
// Mock chainId fetch which happens on every page for wallet connection
cy.mockGQL((req) => {
aliasQuery(req, 'ChainId', {
statistics: { __typename: 'Statistics', chainId: 'test-chain-id' },
statistics: {
__typename: 'Statistics',
chainId: 'vega-fairground-202210041151',
},
});
});
});

View File

@ -53,7 +53,7 @@ describe('withdraw', { tags: '@smoke' }, () => {
cy.get(toAddressField).should('have.value', ethAddressValue);
});
it('min amount', () => {
cy.get(assetSelectField).select(asset1Name); // Select asset so we have a min viable amount calculated
selectAsset(asset1Name);
cy.get(amountField).clear().type('0');
cy.getByTestId(submitWithdrawBtn).click();
cy.get('[data-testid="input-error-text"]').should(
@ -62,7 +62,7 @@ describe('withdraw', { tags: '@smoke' }, () => {
);
});
it('max amount', () => {
cy.get(assetSelectField).select(asset2Name); // Will be above maximum because the vega wallet doesnt have any collateral
selectAsset(asset2Name); // Will be above maximum because the vega wallet doesnt have any collateral
cy.get(amountField).clear().type('1');
cy.getByTestId(submitWithdrawBtn).click();
cy.get('[data-testid="input-error-text"]').should(
@ -72,7 +72,7 @@ describe('withdraw', { tags: '@smoke' }, () => {
});
it('can set amount using use maximum button', () => {
cy.get(assetSelectField).select(asset1Name);
selectAsset(asset1Name);
cy.getByTestId(useMaximumAmount).click();
cy.get(amountField).should('have.value', '1000.00000');
});
@ -87,7 +87,7 @@ describe('withdraw', { tags: '@smoke' }, () => {
},
},
});
cy.get(assetSelectField).select(asset1Name);
selectAsset(asset1Name);
cy.getByTestId('balance-available')
.should('contain.text', 'Balance available')
.find('td')
@ -110,4 +110,13 @@ describe('withdraw', { tags: '@smoke' }, () => {
it.skip('creates a withdrawal on submit'); // Needs capsule
it.skip('creates a withdrawal on submit and prompts to complete withdrawal'); // Needs capsule
const selectAsset = (assetName: string) => {
cy.get(assetSelectField).select(assetName);
// The asset only gets set once the queries (getWithdrawThreshold, getDelay)
// against the Ethereum change resolve, we should fix this but for now just force
// some wait time
// eslint-disable-next-line
cy.wait(1000);
};
});

View File

@ -6,7 +6,7 @@ import { generateChainId } from './mocks/generate-chain-id';
registerCypressGrep();
before(() => {
// Mock chainId fetch which happens on every page for wallet connection
// Mock chainId fetch which happens on every page wallet connection
cy.mockGQL((req) => {
aliasQuery(req, 'ChainId', generateChainId());
});

View File

@ -94,18 +94,18 @@ const headers: Column[] = [
className: cellClassNames,
onlyOnDetailed: false,
},
{
kind: ColumnKind.Asset,
value: t('Settlement asset'),
className: `${cellClassNames} hidden sm:table-cell`,
onlyOnDetailed: false,
},
{
kind: ColumnKind.Sparkline,
value: t(''),
className: `${cellClassNames} hidden lg:table-cell`,
onlyOnDetailed: false,
},
{
kind: ColumnKind.Asset,
value: t('Settlement asset'),
className: `${cellClassNames} hidden sm:table-cell`,
onlyOnDetailed: false,
},
{
kind: ColumnKind.High24,
value: t('24h high'),
@ -209,6 +209,19 @@ export const columns = (
className: cellClassNames,
onlyOnDetailed: false,
},
{
kind: ColumnKind.Sparkline,
value: market.candles && (
<Sparkline
width={100}
height={20}
muted={false}
data={candlesClose?.map((c: string) => Number(c)) || []}
/>
),
className: `${cellClassNames} hidden lg:table-cell`,
onlyOnDetailed: false && candlesClose,
},
{
kind: ColumnKind.Asset,
value: (
@ -231,19 +244,6 @@ export const columns = (
className: `${cellClassNames} hidden sm:table-cell`,
onlyOnDetailed: false,
},
{
kind: ColumnKind.Sparkline,
value: market.candles && (
<Sparkline
width={100}
height={20}
muted={false}
data={candlesClose?.map((c: string) => Number(c)) || []}
/>
),
className: `${cellClassNames} hidden lg:table-cell`,
onlyOnDetailed: false && candlesClose,
},
{
kind: ColumnKind.High24,
value: candleHigh ? (
@ -390,6 +390,19 @@ export const columnsPositionMarkets = (
className: cellClassNames,
onlyOnDetailed: false,
},
{
kind: ColumnKind.Sparkline,
value: candlesClose && (
<Sparkline
width={100}
height={20}
muted={false}
data={candlesClose.map((c: string) => Number(c))}
/>
),
className: `${cellClassNames} hidden lg:table-cell`,
onlyOnDetailed: false,
},
{
kind: ColumnKind.Asset,
value: (
@ -412,19 +425,6 @@ export const columnsPositionMarkets = (
className: `${cellClassNames} hidden sm:table-cell`,
onlyOnDetailed: false,
},
{
kind: ColumnKind.Sparkline,
value: candlesClose && (
<Sparkline
width={100}
height={20}
muted={false}
data={candlesClose.map((c: string) => Number(c))}
/>
),
className: `${cellClassNames} hidden lg:table-cell`,
onlyOnDetailed: false,
},
{
kind: ColumnKind.High24,
value: candleHigh ? (

View File

@ -158,6 +158,16 @@ export const TradeMarketHeader = ({
>
<ExpiryLabel market={market} />
</HeaderStat>
<HeaderStat heading={t('Price')}>
<div data-testid="mark-price">
{market.data && market.data.markPrice !== '0'
? addDecimalsFormatNumber(
market.data.markPrice,
market.decimalPlaces
)
: '-'}
</div>
</HeaderStat>
<HeaderStat heading={t('Change (24h)')}>
<PriceCellChange
candles={candlesClose}
@ -193,16 +203,6 @@ export const TradeMarketHeader = ({
: MarketTradingModeMapping[market.tradingMode]}
</div>
</HeaderStat>
<HeaderStat heading={t('Price')}>
<div data-testid="mark-price">
{market.data && market.data.markPrice !== '0'
? addDecimalsFormatNumber(
market.data.markPrice,
market.decimalPlaces
)
: '-'}
</div>
</HeaderStat>
{symbol ? (
<HeaderStat heading={t('Settlement asset')}>
<div data-testid="trading-mode">

View File

@ -32,28 +32,18 @@ const singleRow = {
const singleRowData = [singleRow];
describe('AccountsTable', () => {
it('should render successfully', async () => {
await act(async () => {
render(<AccountTable rowData={[]} onClickAsset={() => null} />);
});
const headers = await screen.getAllByRole('columnheader');
expect(headers).toHaveLength(6);
expect(
headers?.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim())
).toEqual(['Asset', 'Deposited', 'Used', '', '', '']);
});
it('should render correct columns', async () => {
await act(async () => {
render(
<AccountTable rowData={singleRowData} onClickAsset={() => null} />
);
});
const headers = await screen.getAllByRole('columnheader');
expect(headers).toHaveLength(6);
const expectedHeaders = ['Asset', 'Deposited', 'Used', '', ''];
const headers = await screen.findAllByRole('columnheader');
expect(headers).toHaveLength(expectedHeaders.length);
expect(
headers?.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim())
).toEqual(['Asset', 'Deposited', 'Used', '', '', '']);
).toEqual(expectedHeaders);
});
it('should apply correct formatting', async () => {
@ -62,14 +52,13 @@ describe('AccountsTable', () => {
<AccountTable rowData={singleRowData} onClickAsset={() => null} />
);
});
const cells = await screen.getAllByRole('gridcell');
const cells = await screen.findAllByRole('gridcell');
const expectedValues = [
'tBTC',
'1,256.00000',
'1,256.00001,256.0000',
'Collateral breakdown',
'Deposit',
'Withdraw',
];
cells.forEach((cell, i) => {
expect(cell).toHaveTextContent(expectedValues[i]);

View File

@ -151,43 +151,34 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
}}
/>
<AgGridColumn
colId="transact"
headerName=""
field="deposit"
maxWidth={200}
cellRenderer={({
value,
data,
}: VegaICellRendererParams<AccountFields, 'asset'>) => {
return (
<Button
size="xs"
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit')}
</Button>
);
}}
/>
<AgGridColumn
headerName=""
field="withdraw"
maxWidth={200}
sortable={false}
cellRenderer={({
data,
}: VegaICellRendererParams<AccountFields, 'asset'>) => {
}: VegaICellRendererParams<AccountFields>) => {
return (
<Button
size="xs"
data-testid="withdraw"
onClick={() =>
onClickWithdraw && onClickWithdraw(data.asset.id)
}
>
{t('Withdraw')}
</Button>
<div className="flex gap-2 justify-end">
<Button
size="xs"
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit')}
</Button>
<Button
size="xs"
data-testid="withdraw"
onClick={() =>
onClickWithdraw && onClickWithdraw(data.asset.id)
}
>
{t('Withdraw')}
</Button>
</div>
);
}}
/>

View File

@ -32,16 +32,11 @@ const singleRow = {
const singleRowData = [singleRow];
describe('BreakdownTable', () => {
it('should render successfully', async () => {
const { baseElement } = render(<BreakdownTable data={[]} />);
expect(baseElement).toBeTruthy();
});
it('should render correct columns', async () => {
await act(async () => {
render(<BreakdownTable data={singleRowData} />);
});
const headers = await screen.getAllByRole('columnheader');
const headers = await screen.findAllByRole('columnheader');
expect(headers).toHaveLength(5);
expect(
headers.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim())
@ -52,7 +47,7 @@ describe('BreakdownTable', () => {
await act(async () => {
render(<BreakdownTable data={singleRowData} />);
});
const cells = await screen.getAllByRole('gridcell');
const cells = await screen.findAllByRole('gridcell');
const expectedValues = [
'Margin',
'BTCUSD Monthly (30 Jun 2022)',

View File

@ -12,10 +12,11 @@ import type { ValidationProps } from './use-order-validation';
import { marketTranslations } from './use-order-validation';
import { useOrderValidation } from './use-order-validation';
import { ERROR_SIZE_DECIMAL } from './validate-size';
import type { DealTicketMarketFragment } from '../deal-ticket/__generated__/DealTicket';
jest.mock('@vegaprotocol/wallet');
const market = {
const market: DealTicketMarketFragment = {
id: 'market-id',
decimalPlaces: 2,
positionDecimalPlaces: 1,
@ -25,9 +26,18 @@ const market = {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
id: 'instrument-id',
name: 'instrument-name',
product: {
__typename: 'Future',
quoteName: 'quote-name',
settlementAsset: {
__typename: 'Asset',
id: 'asset-id',
symbol: 'asset-symbol',
name: 'asset-name',
decimals: 2,
},
},
},
},
@ -67,12 +77,12 @@ const ERROR = {
'Only limit orders are permitted when market is in auction',
MARKET_CONTINUOUS_TIF:
'Until the auction ends, you can only place GFA, GTT, or GTC limit orders',
FIELD_SIZE_REQ: 'You need to provide an amount',
FIELD_SIZE_MIN: `The amount cannot be lower than "${defaultOrder.step}"`,
FIELD_SIZE_REQ: 'You need to provide a size',
FIELD_SIZE_MIN: `Size cannot be lower than "${defaultOrder.step}"`,
FIELD_PRICE_REQ: 'You need to provide a price',
FIELD_PRICE_MIN: 'The price cannot be negative',
FIELD_PRICE_STEP_NULL: 'Order sizes must be in whole numbers for this market',
FIELD_PRICE_STEP_DECIMAL: `The amount field accepts up to ${market.positionDecimalPlaces} decimal places`,
FIELD_PRICE_STEP_DECIMAL: `The size field accepts up to ${market.positionDecimalPlaces} decimal places`,
};
function setup(

View File

@ -218,14 +218,14 @@ export const useOrderValidation = ({
if (fieldErrors?.size?.type === 'required') {
return {
isDisabled: true,
message: t('You need to provide an amount'),
message: t('You need to provide a size'),
};
}
if (fieldErrors?.size?.type === 'min') {
return {
isDisabled: true,
message: t(`The amount cannot be lower than "${minSize}"`),
message: t(`Size cannot be lower than "${minSize}"`),
};
}
@ -262,7 +262,7 @@ export const useOrderValidation = ({
return {
isDisabled: true,
message: t(
`The amount field accepts up to ${market.positionDecimalPlaces} decimal places`
`The size field accepts up to ${market.positionDecimalPlaces} decimal places`
),
};
}

View File

@ -1,4 +1,4 @@
import { render, screen, waitFor } from '@testing-library/react';
import { act, render, screen, waitFor } from '@testing-library/react';
import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
import { Side } from '@vegaprotocol/types';
import type { PartialDeep } from 'type-fest';
@ -47,11 +47,12 @@ describe('FillsTable', () => {
});
it('correct columns are rendered', async () => {
render(<FillsTable partyId="party-id" rowData={[generateFill()]} />);
await act(async () => {
render(<FillsTable partyId="party-id" rowData={[generateFill()]} />);
});
await waitForGridToBeInTheDOM();
await waitForDataToHaveLoaded();
await screen.findByText('Market');
const headers = screen.getAllByRole('columnheader');
const expectedHeaders = [
'Market',

View File

@ -54,8 +54,8 @@ export const Radio = ({ id, value, label, disabled }: RadioProps) => {
);
const indicatorClasses = classNames(
'block w-[13px] h-[13px] border-4 rounded-full',
'border-white dark:bg-black',
'dark:border-white dark:bg-black'
'bg-white dark:bg-black',
'border-black dark:border-white'
);
return (
<div className={wrapperClasses}>

View File

@ -132,7 +132,7 @@ const getIntent = (transaction: VegaTxState) => {
case VegaTxStatus.Requested:
return Intent.Warning;
case VegaTxStatus.Pending:
return Intent.Warning;
return Intent.None;
case VegaTxStatus.Error:
return Intent.Danger;
case VegaTxStatus.Complete: