test: added tests to cover submit orders ac (#1708)
* test: added tests to cover submit orders ac * fix: unit tests * fix: mock subscription fixed * fix: typo * fix: lint * fix(1593): remove ag-grid api presence check from providder update callbacks * fix: unit tests Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
This commit is contained in:
parent
5152e3f603
commit
50df63c858
@ -22,15 +22,9 @@ const AccountsManager = () => {
|
||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||
const update = useCallback(
|
||||
({ data }: { data: AccountFields[] | null }) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
if (dataRef.current?.length) {
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[gridRef]
|
||||
);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { MarketState, MarketTradingModeMapping } from '@vegaprotocol/types';
|
||||
import { mockTradingPage } from '../support/trading';
|
||||
import { connectVegaWallet } from '../support/vega-wallet';
|
||||
|
||||
const marketInfoBtn = 'Info';
|
||||
const row = 'key-value-table-row';
|
||||
@ -201,3 +202,45 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('market states', { tags: '@smoke' }, function () {
|
||||
//7002-SORD-062
|
||||
//7002-SORD-063
|
||||
//7002-SORD-066
|
||||
|
||||
const states = [
|
||||
MarketState.STATE_REJECTED,
|
||||
MarketState.STATE_CANCELLED,
|
||||
MarketState.STATE_CLOSED,
|
||||
MarketState.STATE_SETTLED,
|
||||
MarketState.STATE_TRADING_TERMINATED,
|
||||
];
|
||||
|
||||
states.forEach((marketState) => {
|
||||
describe(marketState, function () {
|
||||
before(function () {
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(req, marketState);
|
||||
});
|
||||
cy.mockGQLSubscription();
|
||||
cy.visit('/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
connectVegaWallet();
|
||||
});
|
||||
it.skip('must display correct market state');
|
||||
//7002-/SORD-/061 no state displayed
|
||||
it('must display that market is not accepting orders', function () {
|
||||
cy.getByTestId('dealticket-error-message').should(
|
||||
'have.text',
|
||||
`This market is ${marketState
|
||||
.split('_')
|
||||
.pop()
|
||||
?.toLowerCase()} and not accepting orders`
|
||||
);
|
||||
});
|
||||
it('must have place order button disabled', function () {
|
||||
cy.getByTestId('place-order').should('be.disabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -30,13 +30,15 @@ describe('markets table', { tags: '@regression' }, () => {
|
||||
cy.wait('@MarketsCandles');
|
||||
openMarketDropDown();
|
||||
cy.getByTestId('price').invoke('text').should('not.be.empty');
|
||||
cy.getByTestId('trading-mode').should('not.be.empty');
|
||||
cy.getByTestId('trading-mode-col').should('not.be.empty');
|
||||
cy.getByTestId('taker-fee').should('contain.text', '%');
|
||||
cy.getByTestId('market-volume').should('not.be.empty');
|
||||
cy.getByTestId('market-name').should('not.be.empty');
|
||||
});
|
||||
|
||||
it('Able to select market from dropdown', () => {
|
||||
// 7002-SORD-001
|
||||
// 7002-SORD-002
|
||||
cy.visit('/');
|
||||
cy.wait('@Markets');
|
||||
cy.wait('@MarketsData');
|
||||
@ -47,6 +49,7 @@ describe('markets table', { tags: '@regression' }, () => {
|
||||
cy.wait('@Market');
|
||||
cy.contains('ACTIVE MARKET');
|
||||
cy.url().should('include', '/markets/market-0');
|
||||
cy.getByTestId('popover-trigger').should('not.be.empty');
|
||||
verifyMarketSummaryDisplayed();
|
||||
});
|
||||
|
||||
@ -103,7 +106,7 @@ describe('markets table', { tags: '@regression' }, () => {
|
||||
cy.visit('/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
|
||||
cy.getByTestId('trading-mode').eq(0).realHover();
|
||||
cy.getByTestId('trading-mode').realHover();
|
||||
cy.getByTestId('tooltip-market-info').within(() => {
|
||||
cy.get('span')
|
||||
.eq(0)
|
||||
@ -141,6 +144,7 @@ describe('markets table', { tags: '@regression' }, () => {
|
||||
const tradingMode = 'trading-mode';
|
||||
|
||||
cy.getByTestId(marketSummaryBlock).within(() => {
|
||||
cy.getByTestId('trading-mode').should('not.be.empty');
|
||||
cy.contains('Change (24h)');
|
||||
cy.getByTestId(percentageValue).should('not.be.empty');
|
||||
cy.getByTestId(priceChangeValue).should('not.be.empty');
|
||||
|
@ -1,7 +1,56 @@
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import {
|
||||
MarketState,
|
||||
MarketTradingMode,
|
||||
AuctionTrigger,
|
||||
} from '@vegaprotocol/types';
|
||||
import { mockTradingPage } from '../support/trading';
|
||||
import { connectVegaWallet } from '../support/vega-wallet';
|
||||
|
||||
const orderSizeField = 'order-size';
|
||||
const orderPriceField = 'order-price';
|
||||
const orderTIFDropDown = 'order-tif';
|
||||
const placeOrderBtn = 'place-order';
|
||||
const dialogTitle = 'dialog-title';
|
||||
const orderTransactionHash = 'tx-block-explorer';
|
||||
const toggleShort = 'order-side-SIDE_SELL';
|
||||
const toggleLong = 'order-side-SIDE_BUY';
|
||||
const toggleLimit = 'order-type-TYPE_LIMIT';
|
||||
const toggleMarket = 'order-type-TYPE_MARKET';
|
||||
const errorMessage = 'dealticket-error-message';
|
||||
|
||||
const TIFlist = [
|
||||
{
|
||||
code: 'GTT',
|
||||
value: 'TIME_IN_FORCE_GTT',
|
||||
text: `Good 'til Time (GTT)`,
|
||||
},
|
||||
{
|
||||
code: 'GTC',
|
||||
value: 'TIME_IN_FORCE_GTC',
|
||||
text: `Good 'til Cancelled (GTC)`,
|
||||
},
|
||||
{
|
||||
code: 'IOC',
|
||||
value: 'TIME_IN_FORCE_IOC',
|
||||
text: `Immediate or Cancel (IOC)`,
|
||||
},
|
||||
{
|
||||
code: 'FOK',
|
||||
value: 'TIME_IN_FORCE_FOK',
|
||||
text: `Fill or Kill (FOK)`,
|
||||
},
|
||||
{
|
||||
code: 'GFN',
|
||||
value: 'TIME_IN_FORCE_GFN',
|
||||
text: `Good for Normal (GFN)`,
|
||||
},
|
||||
{
|
||||
code: 'GFA',
|
||||
value: 'TIME_IN_FORCE_GFA',
|
||||
text: `Good for Auction (GFA)`,
|
||||
},
|
||||
];
|
||||
|
||||
interface Order {
|
||||
type: 'TYPE_MARKET' | 'TYPE_LIMIT';
|
||||
side: 'SIDE_BUY' | 'SIDE_SELL';
|
||||
@ -27,7 +76,52 @@ const mockTx = {
|
||||
},
|
||||
};
|
||||
|
||||
describe('deal ticket orders', { tags: '@smoke' }, () => {
|
||||
const testOrder = (order: Order, expected?: Partial<Order>) => {
|
||||
const { type, side, size, price, timeInForce, expiresAt } = order;
|
||||
|
||||
cy.getByTestId(`order-type-${type}`).click();
|
||||
cy.getByTestId(`order-side-${side}`).click();
|
||||
cy.getByTestId(orderSizeField).clear().type(size);
|
||||
if (price) {
|
||||
cy.getByTestId(orderPriceField).clear().type(price);
|
||||
}
|
||||
cy.getByTestId(orderTIFDropDown).select(timeInForce);
|
||||
if (timeInForce === 'TIME_IN_FORCE_GTT') {
|
||||
if (!expiresAt) {
|
||||
throw new Error('Specify expiresAt if using GTT');
|
||||
}
|
||||
// select expiry
|
||||
cy.getByTestId('date-picker-field').type(expiresAt);
|
||||
}
|
||||
cy.getByTestId(placeOrderBtn).click();
|
||||
|
||||
const expectedOrder = {
|
||||
...order,
|
||||
...expected,
|
||||
};
|
||||
|
||||
cy.wait('@VegaCommandSync')
|
||||
.its('request.body')
|
||||
.should('deep.equal', {
|
||||
pubKey: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
propagate: true,
|
||||
orderSubmission: {
|
||||
marketId: 'market-0',
|
||||
...expectedOrder,
|
||||
},
|
||||
});
|
||||
cy.getByTestId(dialogTitle).should(
|
||||
'have.text',
|
||||
'Awaiting network confirmation'
|
||||
);
|
||||
cy.getByTestId(orderTransactionHash)
|
||||
.invoke('attr', 'href')
|
||||
.should('include', 'https://explorer.fairground.wtf/txs/0xtest-tx-hash');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
};
|
||||
|
||||
describe('must submit order', { tags: '@smoke' }, () => {
|
||||
// 7002-SORD-039
|
||||
before(() => {
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(req, MarketState.STATE_ACTIVE);
|
||||
@ -39,6 +133,7 @@ describe('deal ticket orders', { tags: '@smoke' }, () => {
|
||||
});
|
||||
|
||||
it('successfully places market buy order', () => {
|
||||
//7002-SORD-010
|
||||
cy.mockVegaCommandSync(mockTx);
|
||||
const order: Order = {
|
||||
type: 'TYPE_MARKET',
|
||||
@ -61,6 +156,7 @@ describe('deal ticket orders', { tags: '@smoke' }, () => {
|
||||
});
|
||||
|
||||
it('successfully places limit buy order', () => {
|
||||
// 7002-SORD-017
|
||||
cy.mockVegaCommandSync(mockTx);
|
||||
const order: Order = {
|
||||
type: 'TYPE_LIMIT',
|
||||
@ -101,61 +197,10 @@ describe('deal ticket orders', { tags: '@smoke' }, () => {
|
||||
});
|
||||
});
|
||||
|
||||
const testOrder = (order: Order, expected?: Partial<Order>) => {
|
||||
const orderSizeField = 'order-size';
|
||||
const orderPriceField = 'order-price';
|
||||
const orderTIFDropDown = 'order-tif';
|
||||
const placeOrderBtn = 'place-order';
|
||||
const dialogTitle = 'dialog-title';
|
||||
const orderTransactionHash = 'tx-block-explorer';
|
||||
|
||||
const { type, side, size, price, timeInForce, expiresAt } = order;
|
||||
|
||||
cy.get(`[name="order-type"][value="${type}"`).click({ force: true }); // force as input is hidden and displayed as a button
|
||||
cy.get(`[name="order-side"][value="${side}"`).click({ force: true });
|
||||
cy.getByTestId(orderSizeField).clear().type(size);
|
||||
if (price) {
|
||||
cy.getByTestId(orderPriceField).clear().type(price);
|
||||
}
|
||||
cy.getByTestId(orderTIFDropDown).select(timeInForce);
|
||||
if (timeInForce === 'TIME_IN_FORCE_GTT') {
|
||||
if (!expiresAt) {
|
||||
throw new Error('Specify expiresAt if using GTT');
|
||||
}
|
||||
// select expiry
|
||||
cy.getByTestId('date-picker-field').type(expiresAt);
|
||||
}
|
||||
cy.getByTestId(placeOrderBtn).click();
|
||||
|
||||
const expectedOrder = {
|
||||
...order,
|
||||
...expected,
|
||||
};
|
||||
|
||||
cy.wait('@VegaCommandSync')
|
||||
.its('request.body')
|
||||
.should('deep.equal', {
|
||||
pubKey: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
propagate: true,
|
||||
orderSubmission: {
|
||||
marketId: 'market-0',
|
||||
...expectedOrder,
|
||||
},
|
||||
it.skip('must not allow to place an order if balance is 0 (no collateral)', function () {
|
||||
//7002-/SORD-/003
|
||||
// it will be covered in https://github.com/vegaprotocol/frontend-monorepo/issues/1660
|
||||
});
|
||||
cy.getByTestId(dialogTitle).should(
|
||||
'have.text',
|
||||
'Awaiting network confirmation'
|
||||
);
|
||||
cy.getByTestId(orderTransactionHash)
|
||||
.invoke('attr', 'href')
|
||||
.should('include', 'https://explorer.fairground.wtf/txs/0xtest-tx-hash');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
};
|
||||
|
||||
it.skip('cannot place an order if market is suspended');
|
||||
it.skip('cannot place an order if size is 0');
|
||||
it.skip('cannot place an order expiry date is invalid');
|
||||
it.skip('unsuccessful order due to no collateral');
|
||||
});
|
||||
|
||||
describe('deal ticket validation', { tags: '@smoke' }, () => {
|
||||
@ -164,13 +209,209 @@ describe('deal ticket validation', { tags: '@smoke' }, () => {
|
||||
mockTradingPage(req, MarketState.STATE_ACTIVE);
|
||||
});
|
||||
cy.visit('/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
});
|
||||
|
||||
it('cannot place an order if wallet is not connected', () => {
|
||||
it('must not place an order if wallet is not connected', () => {
|
||||
cy.getByTestId('connect-vega-wallet'); // Not connected
|
||||
cy.getByTestId('place-order').should('be.disabled');
|
||||
cy.getByTestId('dealticket-error-message').contains(
|
||||
'No public key selected'
|
||||
cy.getByTestId(placeOrderBtn).should('be.disabled');
|
||||
cy.getByTestId(errorMessage).contains('No public key selected');
|
||||
});
|
||||
|
||||
it('must be able to select order direction - long/short', function () {
|
||||
//7002-SORD-004
|
||||
cy.getByTestId(toggleShort).click().children('input').should('be.checked');
|
||||
cy.getByTestId(toggleLong).click().children('input').should('be.checked');
|
||||
});
|
||||
|
||||
it('must be able to select order type - limit/market', function () {
|
||||
//7002-SORD-005
|
||||
//7002-SORD-006
|
||||
//7002-SORD-007
|
||||
cy.getByTestId(toggleLimit).click().children('input').should('be.checked');
|
||||
cy.getByTestId(toggleMarket).click().children('input').should('be.checked');
|
||||
});
|
||||
});
|
||||
|
||||
describe('deal ticket size validation', { tags: '@smoke' }, function () {
|
||||
before(() => {
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(req, MarketState.STATE_ACTIVE);
|
||||
});
|
||||
cy.visit('/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
connectVegaWallet();
|
||||
});
|
||||
it('must warn if order size input has too many digits after the decimal place', function () {
|
||||
//7002-SORD-016
|
||||
cy.getByTestId(orderSizeField).clear().type('1.234');
|
||||
cy.getByTestId(placeOrderBtn).should('be.disabled');
|
||||
cy.getByTestId(errorMessage).should(
|
||||
'have.text',
|
||||
'Order sizes must be in whole numbers for this market'
|
||||
);
|
||||
});
|
||||
|
||||
it('must warn if order size is set to 0', function () {
|
||||
cy.getByTestId(orderSizeField).clear().type('0');
|
||||
cy.getByTestId(placeOrderBtn).should('be.disabled');
|
||||
cy.getByTestId(errorMessage).should(
|
||||
'have.text',
|
||||
'Size cannot be lower than "1"'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('limit order validations', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(req, MarketState.STATE_ACTIVE);
|
||||
});
|
||||
cy.visit('/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
});
|
||||
|
||||
it('must see the price unit', function () {
|
||||
//7002-SORD-018
|
||||
cy.getByTestId(orderPriceField)
|
||||
.siblings('label')
|
||||
.should('have.text', 'Price (BTC)');
|
||||
});
|
||||
|
||||
it.skip('must see warning when placing an order with expiry date in past', function () {
|
||||
// Test to be created after the bug below is fixed
|
||||
// https://github.com/vegaprotocol/frontend-monorepo/issues/1694
|
||||
});
|
||||
|
||||
it.skip('must receive warning if price has too many digits after decimal place', function () {
|
||||
//7002/-SORD-/059
|
||||
// Skipped until https://github.com/vegaprotocol/frontend-monorepo/issues/1686 resolved
|
||||
});
|
||||
|
||||
describe('time in force validations', function () {
|
||||
it('must have limit order set to GTC by default', function () {
|
||||
//7002-SORD-031
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
TIFlist.filter((item) => item.code === 'GTC')[0].text
|
||||
);
|
||||
});
|
||||
|
||||
const validTIF = TIFlist;
|
||||
validTIF.forEach((tif) => {
|
||||
//7002-SORD-023
|
||||
//7002-SORD-024
|
||||
//7002-SORD-025
|
||||
//7002-SORD-026
|
||||
//7002-SORD-027
|
||||
//7002-SORD-028
|
||||
|
||||
it(`must be able to select ${tif.code}`, function () {
|
||||
cy.getByTestId(orderTIFDropDown).select(tif.value);
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
tif.text
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('market order validations', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(req, MarketState.STATE_ACTIVE);
|
||||
});
|
||||
cy.visit('/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
cy.getByTestId(toggleMarket).click();
|
||||
});
|
||||
it('must not see the price unit', function () {
|
||||
//7002-SORD-019
|
||||
cy.getByTestId(orderPriceField).should('not.exist');
|
||||
});
|
||||
|
||||
describe('time in force validations', function () {
|
||||
it('must have market order set up to IOC by default', function () {
|
||||
//7002-SORD-031
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
TIFlist.filter((item) => item.code === 'IOC')[0].text
|
||||
);
|
||||
});
|
||||
|
||||
const validTIF = TIFlist.filter((tif) => ['FOK', 'IOC'].includes(tif.code));
|
||||
const invalidTIF = TIFlist.filter(
|
||||
(tif) => !['FOK', 'IOC'].includes(tif.code)
|
||||
);
|
||||
|
||||
validTIF.forEach((tif) => {
|
||||
//7002-SORD-025
|
||||
//7002-SORD-026
|
||||
|
||||
it(`must be able to select ${tif.code}`, function () {
|
||||
cy.getByTestId(orderTIFDropDown).select(tif.value);
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
tif.text
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
invalidTIF.forEach((tif) => {
|
||||
//7002-SORD-023
|
||||
//7002-SORD-024
|
||||
//7002-SORD-027
|
||||
//7002-SORD-028
|
||||
it(`must not be able to select ${tif.code}`, function () {
|
||||
cy.getByTestId(orderTIFDropDown).should('not.contain', tif.text);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('suspended market validation', { tags: '@regression' }, () => {
|
||||
before(() => {
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(
|
||||
req,
|
||||
MarketState.STATE_SUSPENDED,
|
||||
MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||
AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
|
||||
);
|
||||
});
|
||||
cy.visit('/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
connectVegaWallet();
|
||||
});
|
||||
|
||||
it('should show warning for market order', function () {
|
||||
cy.getByTestId(toggleMarket).click();
|
||||
cy.getByTestId(placeOrderBtn).should('be.disabled');
|
||||
cy.getByTestId(errorMessage).should(
|
||||
'have.text',
|
||||
'This market is in auction until it reaches sufficient liquidity. Only limit orders are permitted when market is in auction'
|
||||
);
|
||||
});
|
||||
it('should show info for allowed TIF', function () {
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
cy.getByTestId(placeOrderBtn).should('be.enabled');
|
||||
cy.getByTestId(errorMessage).should(
|
||||
'have.text',
|
||||
'Any orders placed now will not trade until the auction ends'
|
||||
);
|
||||
});
|
||||
|
||||
it('should show warning for not allowed TIF', function () {
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
cy.getByTestId(orderTIFDropDown).select(
|
||||
TIFlist.filter((item) => item.code === 'FOK')[0].value
|
||||
);
|
||||
cy.getByTestId(placeOrderBtn).should('be.disabled');
|
||||
cy.getByTestId(errorMessage).should(
|
||||
'have.text',
|
||||
'This market is in auction until it reaches sufficient liquidity. Until the auction ends, you can only place GFA, GTT, or GTC limit orders'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -1,34 +1,15 @@
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import {
|
||||
MarketState,
|
||||
OrderRejectionReason,
|
||||
OrderStatus,
|
||||
} from '@vegaprotocol/types';
|
||||
import { mockTradingPage } from '../support/trading';
|
||||
import type { onMessage } from '@vegaprotocol/cypress';
|
||||
import type {
|
||||
OrderSub as OrderSubData,
|
||||
OrderSubVariables,
|
||||
} from '@vegaprotocol/orders';
|
||||
import { connectVegaWallet } from '../support/vega-wallet';
|
||||
import {
|
||||
updateOrder,
|
||||
getSubscriptionMocks,
|
||||
} from '../support/mocks/generate-ws-order-update';
|
||||
|
||||
const onOrderSub: onMessage<OrderSubData, OrderSubVariables> = function (send) {
|
||||
send({
|
||||
orders: [],
|
||||
});
|
||||
};
|
||||
|
||||
const subscriptionMocks = { OrderSub: onOrderSub };
|
||||
|
||||
before(() => {
|
||||
cy.spy(subscriptionMocks, 'OrderSub');
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(req, MarketState.STATE_ACTIVE);
|
||||
});
|
||||
cy.mockGQLSubscription(subscriptionMocks);
|
||||
cy.visit('/markets/market-0');
|
||||
cy.getByTestId('Orders').click();
|
||||
cy.getByTestId('tab-orders').contains('Please connect Vega wallet');
|
||||
|
||||
connectVegaWallet();
|
||||
});
|
||||
|
||||
describe('orders', { tags: '@smoke' }, () => {
|
||||
const orderSymbol = 'market.tradableInstrument.instrument.code';
|
||||
const orderSize = 'size';
|
||||
const orderType = 'type';
|
||||
@ -40,6 +21,22 @@ describe('orders', { tags: '@smoke' }, () => {
|
||||
const cancelOrderBtn = 'cancel';
|
||||
const editOrderBtn = 'edit';
|
||||
|
||||
describe('orders list', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
const subscriptionMocks = getSubscriptionMocks();
|
||||
cy.spy(subscriptionMocks, 'OrderSub');
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(req, MarketState.STATE_ACTIVE);
|
||||
});
|
||||
cy.mockGQLSubscription(subscriptionMocks);
|
||||
cy.visit('/markets/market-0');
|
||||
cy.getByTestId('Orders').click();
|
||||
cy.getByTestId('tab-orders').contains('Please connect Vega wallet');
|
||||
connectVegaWallet();
|
||||
cy.wait('@Orders').then(() => {
|
||||
expect(subscriptionMocks.OrderSub).to.be.calledOnce;
|
||||
});
|
||||
});
|
||||
it('renders orders', () => {
|
||||
cy.getByTestId('tab-orders').should('be.visible');
|
||||
|
||||
@ -130,3 +127,141 @@ describe('orders', { tags: '@smoke' }, () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('subscribe orders', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
const subscriptionMocks = getSubscriptionMocks();
|
||||
cy.spy(subscriptionMocks, 'OrderSub');
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(req, MarketState.STATE_ACTIVE);
|
||||
});
|
||||
cy.mockGQLSubscription(subscriptionMocks);
|
||||
cy.visit('/markets/market-0');
|
||||
cy.getByTestId('Orders').click();
|
||||
cy.getByTestId('tab-orders').contains('Please connect Vega wallet');
|
||||
connectVegaWallet();
|
||||
cy.wait('@Orders').then(() => {
|
||||
expect(subscriptionMocks.OrderSub).to.be.calledOnce;
|
||||
});
|
||||
});
|
||||
const orderId = '1234567890';
|
||||
//7002-SORD-053
|
||||
//7002-SORD-040
|
||||
it('must see an active order', () => {
|
||||
// 7002-SORD-041
|
||||
updateOrder({
|
||||
id: orderId,
|
||||
status: OrderStatus.STATUS_ACTIVE,
|
||||
});
|
||||
cy.get(`[row-id=${orderId}]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get(`[col-id=${orderStatus}]`).should('have.text', 'Active');
|
||||
});
|
||||
});
|
||||
|
||||
it('must see an expired order', () => {
|
||||
// 7002-SORD-042
|
||||
updateOrder({
|
||||
id: orderId,
|
||||
status: OrderStatus.STATUS_EXPIRED,
|
||||
});
|
||||
cy.get(`[row-id=${orderId}]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get(`[col-id=${orderStatus}]`).should('have.text', 'Expired');
|
||||
});
|
||||
});
|
||||
|
||||
it('must see a cancelled order', () => {
|
||||
// 7002-SORD-043
|
||||
// NOT COVERED: see the txn that cancelled it and a link to the block explorer, if cancelled by a user transaction.
|
||||
updateOrder({
|
||||
id: orderId,
|
||||
status: OrderStatus.STATUS_CANCELLED,
|
||||
});
|
||||
cy.get(`[row-id=${orderId}]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get(`[col-id=${orderStatus}]`).should('have.text', 'Cancelled');
|
||||
});
|
||||
});
|
||||
|
||||
it('must see a stopped order', () => {
|
||||
// 7002-SORD-044
|
||||
// NOT COVERED: see an explanation of why stopped
|
||||
updateOrder({
|
||||
id: orderId,
|
||||
status: OrderStatus.STATUS_STOPPED,
|
||||
});
|
||||
cy.get(`[row-id=${orderId}]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get(`[col-id=${orderStatus}]`).should('have.text', 'Stopped');
|
||||
});
|
||||
});
|
||||
|
||||
it('must see a partially filled order', () => {
|
||||
// 7002-SORD-045
|
||||
updateOrder({
|
||||
id: orderId,
|
||||
status: OrderStatus.STATUS_PARTIALLY_FILLED,
|
||||
size: '5',
|
||||
remaining: '1',
|
||||
});
|
||||
cy.get(`[row-id=${orderId}]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get(`[col-id=${orderStatus}]`).should(
|
||||
'have.text',
|
||||
'PartiallyFilled'
|
||||
);
|
||||
cy.get(`[col-id=${orderRemaining}]`).should('have.text', '4/5');
|
||||
});
|
||||
});
|
||||
|
||||
it('must see a filled order', () => {
|
||||
// 7002-SORD-046
|
||||
// NOT COVERED: Must be able to see/link to all trades that were created from this order
|
||||
updateOrder({
|
||||
id: orderId,
|
||||
status: OrderStatus.STATUS_FILLED,
|
||||
});
|
||||
cy.get(`[row-id=${orderId}]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get(`[col-id=${orderStatus}]`).should('have.text', 'Filled');
|
||||
});
|
||||
});
|
||||
|
||||
it('must see a rejected order', () => {
|
||||
// 7002-SORD-047
|
||||
updateOrder({
|
||||
id: orderId,
|
||||
status: OrderStatus.STATUS_REJECTED,
|
||||
rejectionReason: OrderRejectionReason.ORDER_ERROR_INTERNAL_ERROR,
|
||||
});
|
||||
cy.get(`[row-id=${orderId}]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get(`[col-id=${orderStatus}]`).should(
|
||||
'have.text',
|
||||
'Rejected: Internal error'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('must see a parked order', () => {
|
||||
// 7002-SORD-048
|
||||
// NOT COVERED: must see an explanation of why parked orders happen
|
||||
updateOrder({
|
||||
id: orderId,
|
||||
status: OrderStatus.STATUS_PARKED,
|
||||
});
|
||||
cy.get(`[row-id=${orderId}]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get(`[col-id=${orderStatus}]`).should('have.text', 'Parked');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,52 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type {
|
||||
OrderSub as OrderSubData,
|
||||
OrderSubVariables,
|
||||
OrderSub_orders,
|
||||
} from '@vegaprotocol/orders';
|
||||
|
||||
import type { onMessage } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
OrderStatus,
|
||||
OrderTimeInForce,
|
||||
OrderType,
|
||||
Side,
|
||||
} from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
let sendOrderUpdate: (data: OrderSubData) => void;
|
||||
const getOnOrderSub = () => {
|
||||
const onOrderSub: onMessage<OrderSubData, OrderSubVariables> = (send) => {
|
||||
sendOrderUpdate = send;
|
||||
};
|
||||
return onOrderSub;
|
||||
};
|
||||
|
||||
export const getSubscriptionMocks = () => ({ OrderSub: getOnOrderSub() });
|
||||
|
||||
export function updateOrder(override?: PartialDeep<OrderSub_orders>): void {
|
||||
const order: OrderSub_orders = {
|
||||
__typename: 'OrderUpdate',
|
||||
id: '1234567890',
|
||||
marketId: 'market-0',
|
||||
size: '10',
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
status: OrderStatus.STATUS_FILLED,
|
||||
rejectionReason: null,
|
||||
side: Side.SIDE_BUY,
|
||||
remaining: '0',
|
||||
price: '20000000',
|
||||
timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
createdAt: new Date(2020, 1, 30).toISOString(),
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
liquidityProvisionId: null,
|
||||
peggedOrder: null,
|
||||
};
|
||||
const update: OrderSubData = {
|
||||
orders: [merge(order, override)],
|
||||
};
|
||||
if (!sendOrderUpdate) {
|
||||
throw new Error('OrderSub not called');
|
||||
}
|
||||
sendOrderUpdate(update);
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import type { MarketState } from '@vegaprotocol/types';
|
||||
import type {
|
||||
MarketState,
|
||||
MarketTradingMode,
|
||||
AuctionTrigger,
|
||||
} from '@vegaprotocol/types';
|
||||
import type { CyHttpMessages } from 'cypress/types/net-stubbing';
|
||||
import { generateAccounts } from './mocks/generate-accounts';
|
||||
import { generateAsset, generateAssets } from './mocks/generate-assets';
|
||||
@ -20,7 +24,9 @@ import { generateTrades } from './mocks/generate-trades';
|
||||
|
||||
export const mockTradingPage = (
|
||||
req: CyHttpMessages.IncomingHttpRequest,
|
||||
state: MarketState
|
||||
state: MarketState,
|
||||
tradingMode?: MarketTradingMode,
|
||||
trigger?: AuctionTrigger
|
||||
) => {
|
||||
aliasQuery(
|
||||
req,
|
||||
@ -33,6 +39,7 @@ export const mockTradingPage = (
|
||||
},
|
||||
},
|
||||
state: state,
|
||||
tradingMode: tradingMode,
|
||||
},
|
||||
})
|
||||
);
|
||||
@ -45,14 +52,34 @@ export const mockTradingPage = (
|
||||
aliasQuery(req, 'Accounts', generateAccounts());
|
||||
aliasQuery(req, 'Positions', generatePositions());
|
||||
aliasQuery(req, 'Margins', generateMargins());
|
||||
aliasQuery(req, 'DealTicket', generateDealTicketQuery({ market: { state } }));
|
||||
aliasQuery(
|
||||
req,
|
||||
'DealTicket',
|
||||
generateDealTicketQuery({
|
||||
market: {
|
||||
state,
|
||||
tradingMode: tradingMode,
|
||||
data: {
|
||||
trigger: trigger,
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
aliasQuery(req, 'Assets', generateAssets());
|
||||
aliasQuery(req, 'Asset', generateAsset());
|
||||
|
||||
aliasQuery(
|
||||
req,
|
||||
'MarketInfoQuery',
|
||||
generateMarketInfoQuery({ market: { state } })
|
||||
generateMarketInfoQuery({
|
||||
market: {
|
||||
state,
|
||||
tradingMode: tradingMode,
|
||||
data: {
|
||||
trigger: trigger,
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
aliasQuery(req, 'Trades', generateTrades());
|
||||
aliasQuery(req, 'Chart', generateChart());
|
||||
|
@ -290,7 +290,7 @@ export const columns = (
|
||||
: MarketTradingModeMapping[market.tradingMode],
|
||||
className: `${cellClassNames} hidden lg:table-cell`,
|
||||
onlyOnDetailed: true,
|
||||
dataTestId: 'trading-mode',
|
||||
dataTestId: 'trading-mode-col',
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.Volume,
|
||||
@ -471,7 +471,7 @@ export const columnsPositionMarkets = (
|
||||
: MarketTradingModeMapping[market.tradingMode],
|
||||
className: `${cellClassNames} hidden lg:table-cell`,
|
||||
onlyOnDetailed: true,
|
||||
dataTestId: 'trading-mode',
|
||||
dataTestId: 'trading-mode-col',
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.Volume,
|
||||
|
@ -26,15 +26,9 @@ export const AccountManager = ({
|
||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||
const update = useCallback(
|
||||
({ data }: { data: AccountFields[] | null }) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
if (dataRef.current?.length) {
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[gridRef]
|
||||
);
|
||||
|
@ -63,14 +63,14 @@ describe('DealTicket', () => {
|
||||
|
||||
// Assert defaults are used
|
||||
expect(
|
||||
screen.getByTestId(`order-type-${Schema.OrderType.TYPE_MARKET}-selected`)
|
||||
screen.getByTestId(`order-type-${Schema.OrderType.TYPE_MARKET}`)
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('order-side-SIDE_BUY-selected')
|
||||
).toBeInTheDocument();
|
||||
screen.queryByTestId('order-side-SIDE_BUY')?.querySelector('input')
|
||||
).toBeChecked();
|
||||
expect(
|
||||
screen.queryByTestId('order-side-SIDE_SELL-selected')
|
||||
).not.toBeInTheDocument();
|
||||
screen.queryByTestId('order-side-SIDE_SELL')?.querySelector('input')
|
||||
).not.toBeChecked();
|
||||
expect(screen.getByTestId('order-size')).toHaveDisplayValue(
|
||||
String(1 / Math.pow(10, market.positionDecimalPlaces))
|
||||
);
|
||||
@ -91,7 +91,9 @@ describe('DealTicket', () => {
|
||||
render(generateJsx());
|
||||
|
||||
// BUY is selected by default
|
||||
screen.getByTestId('order-side-SIDE_BUY-selected');
|
||||
expect(
|
||||
screen.getByTestId('order-side-SIDE_BUY')?.querySelector('input')
|
||||
).toBeChecked();
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.change(screen.getByTestId('order-size'), {
|
||||
|
@ -27,10 +27,7 @@ export const useFillsList = ({ partyId, gridRef, scrolledToTop }: Props) => {
|
||||
totalCountRef.current += newRows.current;
|
||||
}
|
||||
newRows.current = 0;
|
||||
if (!gridRef.current?.api) {
|
||||
return;
|
||||
}
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
}, [gridRef]);
|
||||
|
||||
const update = useCallback(
|
||||
@ -41,9 +38,6 @@ export const useFillsList = ({ partyId, gridRef, scrolledToTop }: Props) => {
|
||||
data: (TradeEdge | null)[] | null;
|
||||
delta?: Trade[];
|
||||
}) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
if (dataRef.current?.length) {
|
||||
if (!scrolledToTop.current) {
|
||||
const createdAt = dataRef.current?.[0]?.node.createdAt;
|
||||
@ -54,7 +48,7 @@ export const useFillsList = ({ partyId, gridRef, scrolledToTop }: Props) => {
|
||||
}
|
||||
}
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
return true;
|
||||
}
|
||||
dataRef.current = data;
|
||||
|
@ -33,17 +33,11 @@ export const useOrderListData = ({
|
||||
totalCountRef.current += newRows.current;
|
||||
}
|
||||
newRows.current = 0;
|
||||
if (!gridRef.current?.api) {
|
||||
return;
|
||||
}
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
}, [gridRef]);
|
||||
|
||||
const update = useCallback(
|
||||
({ data, delta }: { data: (OrderEdge | null)[]; delta?: Order[] }) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
if (dataRef.current?.length) {
|
||||
if (!scrolledToTop.current) {
|
||||
const createdAt = dataRef.current?.[0]?.node.createdAt;
|
||||
@ -54,7 +48,7 @@ export const useOrderListData = ({
|
||||
}
|
||||
}
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
return true;
|
||||
}
|
||||
dataRef.current = data;
|
||||
|
@ -44,11 +44,8 @@ export const usePositionsData = (
|
||||
const dataRef = useRef<Position[] | null>(null);
|
||||
const update = useCallback(
|
||||
({ data }: { data: Position[] | null }) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
dataRef.current = assetSymbol ? filter(data, { assetSymbol }) : data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
return true;
|
||||
},
|
||||
[assetSymbol, gridRef]
|
||||
|
@ -49,11 +49,10 @@ export const makeInfiniteScrollGetRows =
|
||||
const rowsThisBlock = data.current
|
||||
? data.current.slice(startRow, endRow).map((edge) => edge?.node)
|
||||
: [];
|
||||
successCallback(
|
||||
rowsThisBlock,
|
||||
const lastRow =
|
||||
getLastRow(startRow, endRow, rowsThisBlock.length, totalCount.current) -
|
||||
newRows.current
|
||||
);
|
||||
newRows.current;
|
||||
successCallback(rowsThisBlock, lastRow);
|
||||
} catch (e) {
|
||||
failCallback();
|
||||
}
|
||||
|
@ -35,10 +35,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
||||
totalCountRef.current += newRows.current;
|
||||
}
|
||||
newRows.current = 0;
|
||||
if (!gridRef.current?.api) {
|
||||
return;
|
||||
}
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
}, []);
|
||||
|
||||
const update = useCallback(
|
||||
@ -49,9 +46,6 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
||||
data: (TradeEdge | null)[] | null;
|
||||
delta?: Trade[];
|
||||
}) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
if (dataRef.current?.length) {
|
||||
if (!scrolledToTop.current) {
|
||||
const createdAt = dataRef.current?.[0]?.node.createdAt;
|
||||
@ -62,7 +56,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
||||
}
|
||||
}
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
gridRef.current?.api.refreshInfiniteCache();
|
||||
return true;
|
||||
}
|
||||
dataRef.current = data;
|
||||
|
@ -42,9 +42,13 @@ export const Toggle = ({
|
||||
return (
|
||||
<fieldset className={fieldsetClasses} {...props}>
|
||||
{toggles.map(({ label, value }, key) => {
|
||||
const isSelected = value === checkedValue;
|
||||
return (
|
||||
<label key={key} className={labelClasses} htmlFor={label}>
|
||||
<label
|
||||
key={key}
|
||||
className={labelClasses}
|
||||
htmlFor={label}
|
||||
data-testid={`${name}-${value}`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
id={label}
|
||||
@ -56,14 +60,7 @@ export const Toggle = ({
|
||||
}
|
||||
className={radioClasses}
|
||||
/>
|
||||
<span
|
||||
className={buttonClasses}
|
||||
data-testid={
|
||||
isSelected ? `${name}-${value}-selected` : `${name}-${value}`
|
||||
}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
<span className={buttonClasses}>{label}</span>
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
|
Loading…
Reference in New Issue
Block a user