feat: [console-lite] - trading - direction selector (#812)
* feat: [console-lite] - trading - direction selector * feat: [console-lite] - trading - direction selector - add int tests * feat: [console-lite] - trading - direction selector - fixes after review feedback * feat: [console-lite] - trading - direction selector - fix accidentaly failling int test * feat: [console-lite] - trading - direction selector - fix accidentaly failling int test Co-authored-by: maciek <maciek@vegaprotocol.io>
This commit is contained in:
parent
556be89bfd
commit
d5c8892406
@ -9,14 +9,14 @@ describe('market selector', () => {
|
||||
});
|
||||
cy.visit('/markets');
|
||||
cy.wait('@gqlSimpleMarketsQuery').then((response) => {
|
||||
if (response.response?.body?.data?.markets?.length) {
|
||||
markets = response.response?.body?.data?.markets;
|
||||
if (response.response.body.data?.markets?.length) {
|
||||
markets = response.response.body.data.markets;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should be properly rendered', () => {
|
||||
if (markets) {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
cy.get('input[placeholder="Search"]').should(
|
||||
'have.value',
|
||||
@ -34,7 +34,7 @@ describe('market selector', () => {
|
||||
});
|
||||
|
||||
it('typing should change list', () => {
|
||||
if (markets) {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
cy.get('input[placeholder="Search"]').type('{backspace}');
|
||||
cy.getByTestId('market-pane')
|
||||
@ -65,7 +65,7 @@ describe('market selector', () => {
|
||||
});
|
||||
|
||||
it('mobile view', () => {
|
||||
if (markets) {
|
||||
if (markets?.length) {
|
||||
cy.viewport('iphone-xr');
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
cy.get('[role="dialog"]').should('not.exist');
|
||||
|
@ -0,0 +1,67 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import { generateSimpleMarkets } from '../support/mocks/generate-markets';
|
||||
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
|
||||
|
||||
describe('Market trade', () => {
|
||||
let markets;
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'DealTicketQuery', generateDealTicket());
|
||||
});
|
||||
cy.visit('/markets');
|
||||
cy.wait('@SimpleMarkets').then((response) => {
|
||||
if (response.response.body.data?.markets?.length) {
|
||||
markets = response.response.body.data.markets;
|
||||
}
|
||||
});
|
||||
});
|
||||
it('side selector should work well', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').should(
|
||||
'have.text',
|
||||
'Long'
|
||||
);
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').click();
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('#step-2-control').click();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').should(
|
||||
'have.text',
|
||||
'Short'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('mobile view should work well', () => {
|
||||
if (markets?.length) {
|
||||
cy.viewport('iphone-xr');
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
cy.getByTestId('next-button').scrollIntoView().click();
|
||||
|
||||
cy.get('button[aria-label="Open long position"]').should(
|
||||
'have.class',
|
||||
'selected'
|
||||
);
|
||||
cy.get('button[aria-label="Open short position"]').should(
|
||||
'not.have.class',
|
||||
'selected'
|
||||
);
|
||||
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('button[aria-label="Open long position"]').should(
|
||||
'not.have.class',
|
||||
'selected'
|
||||
);
|
||||
cy.get('button[aria-label="Open short position"]').should(
|
||||
'have.class',
|
||||
'selected'
|
||||
);
|
||||
cy.getByTestId('next-button').scrollIntoView().click();
|
||||
cy.get('#step-1-control').should(
|
||||
'contain.html',
|
||||
'aria-label="Selected value Short"'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
@ -0,0 +1,33 @@
|
||||
export const generateDealTicket = () => {
|
||||
return {
|
||||
market: {
|
||||
id: 'first-btcusd-id',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
state: 'Active',
|
||||
tradingMode: 'Continuous',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
quoteName: 'DAI',
|
||||
settlementAsset: {
|
||||
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
|
||||
symbol: 'tDAI',
|
||||
name: 'tDAI TEST',
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
depth: {
|
||||
lastTrade: { price: '9893006', __typename: 'Trade' },
|
||||
__typename: 'MarketDepth',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
};
|
1069
apps/simple-trading-app-e2e/src/support/mocks/generate-markets.ts
Normal file
1069
apps/simple-trading-app-e2e/src/support/mocks/generate-markets.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,11 +3,7 @@ import { useForm, Controller } from 'react-hook-form';
|
||||
import { Stepper } from '../stepper';
|
||||
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
|
||||
import { Button, InputError } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
SideSelector,
|
||||
DealTicketAmount,
|
||||
MarketSelector,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import { DealTicketAmount, MarketSelector } from '@vegaprotocol/deal-ticket';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
import { t, addDecimal, toDecimal } from '@vegaprotocol/react-helpers';
|
||||
@ -19,6 +15,7 @@ import {
|
||||
import { useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import MarketNameRenderer from '../simple-market-list/simple-market-renderer';
|
||||
import SideSelector, { SIDE_NAMES } from './side-selector';
|
||||
|
||||
interface DealTicketMarketProps {
|
||||
market: DealTicketQuery_market;
|
||||
@ -47,6 +44,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
|
||||
const step = toDecimal(market.positionDecimalPlaces);
|
||||
const orderType = watch('type');
|
||||
const orderTimeInForce = watch('timeInForce');
|
||||
const orderSide = watch('side');
|
||||
|
||||
const { message: invalidText, isDisabled } = useOrderValidation({
|
||||
step,
|
||||
@ -96,6 +94,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
|
||||
)}
|
||||
/>
|
||||
),
|
||||
value: SIDE_NAMES[orderSide] || '',
|
||||
},
|
||||
{
|
||||
label: t('Choose Position Size'),
|
||||
|
@ -0,0 +1,58 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { FormGroup, Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { VegaWalletOrderSide } from '@vegaprotocol/wallet';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
|
||||
interface SideSelectorProps {
|
||||
value: VegaWalletOrderSide;
|
||||
onSelect: (side: VegaWalletOrderSide) => void;
|
||||
}
|
||||
|
||||
export const SIDE_NAMES: Record<VegaWalletOrderSide, string> = {
|
||||
[VegaWalletOrderSide.Buy]: t('Long'),
|
||||
[VegaWalletOrderSide.Sell]: t('Short'),
|
||||
};
|
||||
|
||||
export default ({ value, onSelect }: SideSelectorProps) => {
|
||||
return (
|
||||
<FormGroup
|
||||
label={t('Direction')}
|
||||
labelFor="order-side-toggle"
|
||||
labelClassName="sr-only"
|
||||
>
|
||||
<fieldset
|
||||
className="w-full grid md:grid-cols-2 gap-20"
|
||||
id="order-side-toggle"
|
||||
>
|
||||
<Button
|
||||
variant="inline-link"
|
||||
aria-label={t('Open long position')}
|
||||
className={classNames(
|
||||
'buyButton hover:buyButton dark:buyButtonDark dark:hover:buyButtonDark',
|
||||
{ selected: value === VegaWalletOrderSide.Buy }
|
||||
)}
|
||||
onClick={() => onSelect(VegaWalletOrderSide.Buy)}
|
||||
>
|
||||
{t('Long')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="inline-link"
|
||||
aria-label={t('Open short position')}
|
||||
className={classNames(
|
||||
'sellButton hover:sellButton dark:sellButtonDark dark:hover:sellButtonDark',
|
||||
{ selected: value === VegaWalletOrderSide.Sell }
|
||||
)}
|
||||
onClick={() => onSelect(VegaWalletOrderSide.Sell)}
|
||||
>
|
||||
{t('Short')}
|
||||
</Button>
|
||||
<div className="md:col-span-2 text-black dark:text-white text-ui-small">
|
||||
{t(
|
||||
'Trading derivatives allows you to make a profit or loss regardless of whether the market you are trading goes up or down. If you open a "long" position, you will make a profit if the price of your chosen market goes up, and you will make a profit for "short" positions when the price goes down.'
|
||||
)}
|
||||
</div>
|
||||
</fieldset>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
@ -66,7 +66,7 @@ const SimpleMarketList = () => {
|
||||
);
|
||||
|
||||
const handleOnGridReady = useCallback(() => {
|
||||
gridRef.current?.api.sizeColumnsToFit();
|
||||
gridRef.current?.api?.sizeColumnsToFit();
|
||||
}, [gridRef]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -146,6 +146,7 @@ export const Stepper = ({ steps }: StepperProps) => {
|
||||
variant="secondary"
|
||||
onClick={handleNext}
|
||||
disabled={steps[activeStep].disabled}
|
||||
data-testid="next-button"
|
||||
>
|
||||
{t('Next')}
|
||||
</Button>
|
||||
|
@ -203,7 +203,7 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
<hr className="md:hidden mb-5" />
|
||||
<hr className="mb-5" />
|
||||
<div
|
||||
className={classNames(
|
||||
'md:absolute z-20 flex flex-col top-[30px] z-10 md:drop-shadow-md md:border-1 md:border-black md:dark:border-white bg-white dark:bg-black text-black dark:text-white min-w-full md:max-h-[200px] overflow-y-auto',
|
||||
|
@ -39,6 +39,58 @@ const vegaCustomClassesLite = plugin(function ({ addUtilities }) {
|
||||
marginTop: '10px',
|
||||
marginRight: '5px',
|
||||
},
|
||||
'.buyButton': {
|
||||
textTransform: 'uppercase',
|
||||
textDecoration: 'none',
|
||||
backgroundColor: 'rgba(0, 143, 74, 0.1)',
|
||||
border: `1px solid ${theme.colors.darkerGreen}`,
|
||||
color: theme.colors.darkerGreen,
|
||||
paddingTop: '0.5rem',
|
||||
paddingBottom: '0.5rem',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.colors.darkerGreen,
|
||||
color: theme.colors.white.DEFAULT,
|
||||
},
|
||||
'&.selected': {
|
||||
backgroundColor: theme.colors.darkerGreen,
|
||||
color: theme.colors.white.DEFAULT,
|
||||
},
|
||||
},
|
||||
'.buyButtonDark': {
|
||||
color: theme.colors.darkerGreen,
|
||||
'&:hover': {
|
||||
color: theme.colors.black.DEFAULT,
|
||||
},
|
||||
'&.selected': {
|
||||
color: theme.colors.black.DEFAULT,
|
||||
},
|
||||
},
|
||||
'.sellButton': {
|
||||
textTransform: 'uppercase',
|
||||
textDecoration: 'none',
|
||||
paddingTop: '0.5rem',
|
||||
paddingBottom: '0.5rem',
|
||||
backgroundColor: 'rgba(255, 8, 126, 0.1)',
|
||||
border: `1px solid ${theme.colors.pink}`,
|
||||
color: theme.colors.pink,
|
||||
'&:hover': {
|
||||
color: theme.colors.white.DEFAULT,
|
||||
backgroundColor: theme.colors.pink,
|
||||
},
|
||||
'&.selected': {
|
||||
backgroundColor: theme.colors.pink,
|
||||
color: theme.colors.white.DEFAULT,
|
||||
},
|
||||
},
|
||||
'.sellButtonDark': {
|
||||
color: theme.colors.pink,
|
||||
'&:hover': {
|
||||
color: theme.colors.black.DEFAULT,
|
||||
},
|
||||
'&.selected': {
|
||||
color: theme.colors.black.DEFAULT,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user