Task/229 Stub api in trading e2e (#211)
* add fixture for markets query * stub graphql requests * re-add assertion for tx hash, stub command/sync requests * refactor to get tests to run with trading page mocked queries * add test wallet credentials * split up markets page from trading page * add portfolio page feature, add market page scenarios * move hasOperationName helper to support/index * fix home-page.feature * fix missing feature step * Minor changes to BDD steps * Use in object syntax to get better type safety on hasOperationName helper function * remove bypass placing orders env var and usage in tests * use UI_Trading_Test wallet publick key in command/sync mock * move public key to cypress env * replace fixtures with generator functions * colocate query generators with queries * add custom commands, add index files * fix dodgy merge, remove duplicate market page feature * make tsconfig for cypress lib match * update tsconfig for explorer e2e so commands using merge work * revert trading step to js Co-authored-by: Joe <joe@vega.xyz>
This commit is contained in:
parent
3db9546266
commit
04872522d6
@ -3,8 +3,16 @@
|
||||
"compilerOptions": {
|
||||
"sourceMap": false,
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": ["cypress", "node"],
|
||||
"allowJs": true,
|
||||
"types": ["cypress", "node"]
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.js"]
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"chromeWebSecurity": false,
|
||||
"projectId": "et4snf",
|
||||
"env": {
|
||||
"bypassPlacingOrders": true,
|
||||
"vegaPublicKey": "47836c253520d2661bf5bed6339c0de08fd02cf5d4db0efee3b4373f20c7d278",
|
||||
"tsConfig": "tsconfig.json",
|
||||
"TAGS": "not @todo and not @ignore and not @manual"
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io"
|
||||
}
|
@ -1,11 +1,8 @@
|
||||
Feature: Market orders
|
||||
|
||||
Feature: Deal ticket
|
||||
Scenario Outline: Successfull market buy orders
|
||||
Given I am on the homepage
|
||||
And I navigate to markets page
|
||||
When I click on active market
|
||||
Given I am on the trading page for an active market
|
||||
And I connect to Vega Wallet
|
||||
And place a buy '<marketOrderType>' market order
|
||||
When I place a buy '<marketOrderType>' market order
|
||||
Then order request is sent
|
||||
|
||||
Examples:
|
||||
@ -14,11 +11,9 @@ Feature: Market orders
|
||||
| IOC |
|
||||
|
||||
Scenario Outline: Successfull Limit buy orders
|
||||
Given I am on the homepage
|
||||
And I navigate to markets page
|
||||
When I click on active market
|
||||
Given I am on the trading page for an active market
|
||||
And I connect to Vega Wallet
|
||||
And place a buy '<limitOrderType>' limit order
|
||||
When I place a buy '<limitOrderType>' limit order
|
||||
Then order request is sent
|
||||
|
||||
Examples:
|
||||
@ -30,11 +25,9 @@ Feature: Market orders
|
||||
| GFN |
|
||||
|
||||
Scenario Outline: Successfull market sell order
|
||||
Given I am on the homepage
|
||||
And I navigate to markets page
|
||||
When I click on active market
|
||||
Given I am on the trading page for an active market
|
||||
And I connect to Vega Wallet
|
||||
And place a sell '<marketOrderType>' market order
|
||||
When I place a sell '<marketOrderType>' market order
|
||||
Then order request is sent
|
||||
|
||||
Examples:
|
||||
@ -43,11 +36,10 @@ Feature: Market orders
|
||||
| IOC |
|
||||
|
||||
Scenario Outline: Successfull limit sell order
|
||||
Given I am on the homepage
|
||||
And I navigate to markets page
|
||||
When I click on active market
|
||||
Given I am on the trading page for an active market
|
||||
And I connect to Vega Wallet
|
||||
And place a sell '<limitOrderType>' limit order
|
||||
When I place a sell '<limitOrderType>' limit order
|
||||
Then order request is sent
|
||||
|
||||
Examples:
|
||||
| limitOrderType |
|
||||
@ -66,27 +58,20 @@ Feature: Market orders
|
||||
And place a buy 'FOK' market order
|
||||
Then error message for insufficient funds is displayed
|
||||
|
||||
@ignore
|
||||
Scenario: Unable to order because market is suspended
|
||||
Given I am on the homepage
|
||||
And I navigate to markets page
|
||||
When I click on suspended market
|
||||
Given I am on the trading page for a suspended market
|
||||
And I connect to Vega Wallet
|
||||
Then place order button is disabled
|
||||
And "Market is currently suspended" error is shown
|
||||
|
||||
Scenario: Unable to order because wallet is not connected
|
||||
Given I am on the homepage
|
||||
And I navigate to markets page
|
||||
When I click on active market
|
||||
Given I am on the trading page for an active market
|
||||
Then place order button is disabled
|
||||
And "No public key selected" error is shown
|
||||
|
||||
@ignore
|
||||
Scenario: Unsuccessfull because quantity is 0
|
||||
Given I am on the homepage
|
||||
And I navigate to markets page
|
||||
When I click on active market
|
||||
Given I am on the trading page for an active market
|
||||
And I connect to Vega Wallet
|
||||
And place a buy 'FOK' market order with amount of 0
|
||||
Then Order rejected by wallet error shown containing text "must be positive"
|
@ -7,6 +7,10 @@ Feature: Home page
|
||||
Given I am on the homepage
|
||||
And I navigate to portfolio page
|
||||
|
||||
Scenario: Visit Markets page
|
||||
Given I am on the homepage
|
||||
And I navigate to markets page
|
||||
|
||||
Scenario: Unable to connect Vega wallet with incorrect credentials
|
||||
Given I am on the homepage
|
||||
When I try to connect Vega wallet with incorrect details
|
||||
|
@ -1,6 +0,0 @@
|
||||
Feature: Market Page
|
||||
|
||||
Scenario: Market table displayed on market page
|
||||
Given I am on the homepage
|
||||
And I navigate to markets page
|
||||
Then the market table is displayed
|
17
apps/trading-e2e/src/integration/markets-page.feature
Normal file
17
apps/trading-e2e/src/integration/markets-page.feature
Normal file
@ -0,0 +1,17 @@
|
||||
Feature: Markets page
|
||||
|
||||
Scenario: Navigation
|
||||
Given I am on the homepage
|
||||
When I navigate to markets page
|
||||
Then I can view markets
|
||||
And the market table is displayed
|
||||
|
||||
Scenario: Select active market
|
||||
Given I am on the markets page
|
||||
When I click on an active market
|
||||
Then I am on the trading page for an active market
|
||||
|
||||
Scenario: Select suspended market
|
||||
Given I am on the markets page
|
||||
When I click on a suspended market
|
||||
Then I am on the trading page for a suspended market
|
5
apps/trading-e2e/src/integration/portfolio-page.feature
Normal file
5
apps/trading-e2e/src/integration/portfolio-page.feature
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
Feature: Portfolio page
|
||||
Scenario: Navigation
|
||||
Given I am on the homepage
|
||||
Then I navigate to portfolio page
|
@ -1 +0,0 @@
|
||||
export const getGreeting = () => cy.get('h1');
|
@ -1,17 +1,11 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import '@vegaprotocol/cypress';
|
||||
import type { CyHttpMessages } from 'cypress/types/net-stubbing';
|
||||
|
||||
// Utility to match GraphQL mutation based on the operation name
|
||||
export const hasOperationName = (
|
||||
req: CyHttpMessages.IncomingHttpRequest,
|
||||
operationName: string
|
||||
) => {
|
||||
const { body } = req;
|
||||
return 'operationName' in body && body.operationName === operationName;
|
||||
};
|
||||
|
@ -1,56 +1,16 @@
|
||||
export default class BasePage {
|
||||
porfolioUrl = '/portfolio';
|
||||
marketsUrl = '/markets';
|
||||
connectVegaBtn = 'connect-vega-wallet';
|
||||
walletConnectors = 'connectors-list';
|
||||
walletForm = 'rest-connector-form';
|
||||
walletInputError = 'input-wallet-error';
|
||||
walletFormError = 'form-error';
|
||||
inputError = 'input-error-text';
|
||||
|
||||
navigateToPortfolio() {
|
||||
cy.get(`a[href='${this.porfolioUrl}']`).click();
|
||||
cy.get(`a[href='${this.porfolioUrl}']`).should('be.visible').click();
|
||||
cy.url().should('include', '/portfolio');
|
||||
cy.getByTestId('portfolio');
|
||||
}
|
||||
|
||||
navigateToMarkets() {
|
||||
cy.get(`a[href='${this.marketsUrl}']`)
|
||||
.should('be.visible')
|
||||
.click({ force: true });
|
||||
cy.get(`a[href='${this.marketsUrl}']`).should('be.visible').click();
|
||||
cy.url().should('include', '/markets');
|
||||
}
|
||||
|
||||
navigateToConnectVegaWallet() {
|
||||
cy.getByTestId(this.connectVegaBtn).click();
|
||||
cy.contains('Connects using REST to a running Vega wallet service');
|
||||
cy.getByTestId(this.walletConnectors).find('button').click();
|
||||
}
|
||||
|
||||
fillInWalletForm(walletName, walletPassphrase) {
|
||||
cy.getByTestId(this.walletForm)
|
||||
.find('#wallet')
|
||||
.click({ force: true })
|
||||
.type(walletName);
|
||||
cy.getByTestId(this.walletForm)
|
||||
.find('#passphrase')
|
||||
.click({ force: true })
|
||||
.type(walletPassphrase);
|
||||
}
|
||||
|
||||
clickConnectVegaWallet() {
|
||||
cy.getByTestId(this.walletForm)
|
||||
.find('button[type=submit]')
|
||||
.click({ force: true });
|
||||
}
|
||||
|
||||
validateWalletNotRunningError() {
|
||||
cy.getByTestId(this.walletFormError).should(
|
||||
'have.text',
|
||||
'Authentication failed'
|
||||
);
|
||||
}
|
||||
|
||||
validateWalletErrorFieldsDisplayed() {
|
||||
cy.getByTestId(this.walletInputError).should('have.text', 'Required');
|
||||
cy.getByTestId(this.inputError).should('have.text', 'Required');
|
||||
cy.getByTestId('markets');
|
||||
}
|
||||
}
|
||||
|
@ -7,15 +7,10 @@ export default class MarketPage extends BasePage {
|
||||
'tradableInstrument.instrument.product.settlementAsset.symbol';
|
||||
marketRowPrices = 'flash-cell';
|
||||
marketRowDescription = 'name';
|
||||
chartTab = 'chart';
|
||||
ticketTab = 'ticket';
|
||||
orderbookTab = 'orderbook';
|
||||
ordersTab = 'orders';
|
||||
positionsTab = 'positions';
|
||||
collateralTab = 'collateral';
|
||||
tradesTab = 'trades';
|
||||
completedTrades = 'market-trades';
|
||||
orderBookTab = 'orderbook';
|
||||
|
||||
validateMarketsAreDisplayed() {
|
||||
cy.get('.ag-root-wrapper').should('be.visible');
|
||||
}
|
||||
|
||||
validateMarketTableDisplayed() {
|
||||
const expectedMarketHeaders = [
|
||||
@ -58,39 +53,7 @@ export default class MarketPage extends BasePage {
|
||||
);
|
||||
}
|
||||
|
||||
validateCompletedTradesDisplayed() {
|
||||
cy.getByTestId(this.completedTrades).should('not.be.empty');
|
||||
}
|
||||
|
||||
clickOnMarket(marketText) {
|
||||
cy.contains(marketText).click();
|
||||
}
|
||||
|
||||
clickOnActiveMarket() {
|
||||
cy.contains('Active', { timeout: 8000 }).click({ force: true });
|
||||
}
|
||||
|
||||
clickOnTopMarketRow() {
|
||||
cy.get('[col-id="data"]').eq(1).click();
|
||||
}
|
||||
|
||||
clickOnOrdersTab() {
|
||||
cy.getByTestId(this.ordersTab).click();
|
||||
}
|
||||
|
||||
clickOnTicketTab() {
|
||||
cy.getByTestId(this.ticketTab).click();
|
||||
}
|
||||
|
||||
clickOnCollateralTab() {
|
||||
cy.getByTestId(this.collateralTab).click();
|
||||
}
|
||||
|
||||
clickOnTradesTab() {
|
||||
cy.getByTestId(this.tradesTab).click();
|
||||
}
|
||||
|
||||
clickOrderBookTab() {
|
||||
cy.getByTestId(this.orderBookTab).click();
|
||||
clickOnMarket(text) {
|
||||
cy.contains(text).click();
|
||||
}
|
||||
}
|
||||
|
3
apps/trading-e2e/src/support/pages/portfolio-page.js
Normal file
3
apps/trading-e2e/src/support/pages/portfolio-page.js
Normal file
@ -0,0 +1,3 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class PortfolioPage extends BasePage {}
|
33
apps/trading-e2e/src/support/pages/trading-page.js
Normal file
33
apps/trading-e2e/src/support/pages/trading-page.js
Normal file
@ -0,0 +1,33 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class TradingPage extends BasePage {
|
||||
chartTab = 'chart';
|
||||
ticketTab = 'ticket';
|
||||
orderbookTab = 'orderbook';
|
||||
ordersTab = 'orders';
|
||||
positionsTab = 'positions';
|
||||
collateralTab = 'collateral';
|
||||
tradesTab = 'trades';
|
||||
completedTrades = 'market-trades';
|
||||
orderBookTab = 'orderbook';
|
||||
|
||||
clickOnOrdersTab() {
|
||||
cy.getByTestId(this.ordersTab).click();
|
||||
}
|
||||
|
||||
clickOnTicketTab() {
|
||||
cy.getByTestId(this.ticketTab).click();
|
||||
}
|
||||
|
||||
clickOnCollateralTab() {
|
||||
cy.getByTestId(this.collateralTab).click();
|
||||
}
|
||||
|
||||
clickOnTradesTab() {
|
||||
cy.getByTestId(this.tradesTab).click();
|
||||
}
|
||||
|
||||
clickOrderBookTab() {
|
||||
cy.getByTestId(this.orderBookTab).click();
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
import { Given, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
import MarketsPage from '../pages/markets-page';
|
||||
import DealTicketPage from '../pages/deal-ticket-page';
|
||||
const marketsPage = new MarketsPage();
|
||||
const dealTicketPage = new DealTicketPage();
|
||||
|
||||
Given('I am on the homepage', () => {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
Given('I navigate to markets page', () => {
|
||||
marketsPage.navigateToMarkets();
|
||||
});
|
||||
|
||||
Given('I navigate to portfolio page', () => {
|
||||
marketsPage.navigateToPortfolio();
|
||||
});
|
||||
|
||||
When('I connect to Vega Wallet', () => {
|
||||
marketsPage.navigateToConnectVegaWallet();
|
||||
marketsPage.fillInWalletForm(
|
||||
'UI_Trading_Test',
|
||||
Cypress.env('tradingWalletPassphrase')
|
||||
);
|
||||
marketsPage.clickConnectVegaWallet();
|
||||
dealTicketPage.reloadPageIfPublicKeyErrorDisplayed();
|
||||
});
|
@ -0,0 +1,5 @@
|
||||
import { Given } from 'cypress-cucumber-preprocessor/steps';
|
||||
|
||||
Given('I am on the homepage', () => {
|
||||
cy.visit('/');
|
||||
});
|
@ -0,0 +1,52 @@
|
||||
import { Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
import DealTicket from '../trading-windows/deal-ticket';
|
||||
|
||||
const dealTicket = new DealTicket();
|
||||
|
||||
When('I place a buy {string} market order', (orderType) => {
|
||||
dealTicket.placeMarketOrder(true, 100, orderType);
|
||||
dealTicket.clickPlaceOrder();
|
||||
});
|
||||
|
||||
When('I place a sell {string} market order', (orderType) => {
|
||||
dealTicket.placeMarketOrder(false, 100, orderType);
|
||||
dealTicket.clickPlaceOrder();
|
||||
});
|
||||
|
||||
When('I place a buy {string} limit order', (limitOrderType) => {
|
||||
dealTicket.placeLimitOrder(true, 100, 2000, limitOrderType);
|
||||
dealTicket.clickPlaceOrder();
|
||||
});
|
||||
|
||||
When('I place a sell {string} limit order', (limitOrderType) => {
|
||||
dealTicket.placeLimitOrder(false, 100, 2000, limitOrderType);
|
||||
dealTicket.clickPlaceOrder();
|
||||
});
|
||||
|
||||
When('I place a buy {string} market order with amount of 0', (orderType) => {
|
||||
dealTicket.placeMarketOrder(true, 0, orderType);
|
||||
dealTicket.clickPlaceOrder();
|
||||
});
|
||||
|
||||
Then('order request is sent', () => {
|
||||
dealTicket.verifyOrderRequestSent();
|
||||
});
|
||||
|
||||
Then('error message for insufficient funds is displayed', () => {
|
||||
dealTicket.verifyOrderFailedInsufficientFunds();
|
||||
});
|
||||
|
||||
Then('place order button is disabled', () => {
|
||||
dealTicket.verifyPlaceOrderBtnDisabled();
|
||||
});
|
||||
|
||||
Then('{string} error is shown', (errorMsg) => {
|
||||
dealTicket.verifySubmitBtnErrorText(errorMsg);
|
||||
});
|
||||
|
||||
Then(
|
||||
'Order rejected by wallet error shown containing text {string}',
|
||||
(expectedError) => {
|
||||
dealTicket.verifyOrderRejected(expectedError);
|
||||
}
|
||||
);
|
@ -1,22 +1,23 @@
|
||||
import { Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
import MarketsPage from '../pages/markets-page';
|
||||
const marketsPage = new MarketsPage();
|
||||
import VegaWallet from '../vega-wallet';
|
||||
|
||||
const vegaWallet = new VegaWallet();
|
||||
|
||||
When('I try to connect Vega wallet with incorrect details', () => {
|
||||
marketsPage.navigateToConnectVegaWallet();
|
||||
marketsPage.fillInWalletForm('name', 'wrong passphrase');
|
||||
marketsPage.clickConnectVegaWallet();
|
||||
vegaWallet.openVegaWalletConnectDialog();
|
||||
vegaWallet.fillInWalletForm('name', 'wrong passphrase');
|
||||
vegaWallet.clickConnectVegaWallet();
|
||||
});
|
||||
|
||||
When('I try to connect Vega wallet with blank fields', () => {
|
||||
marketsPage.navigateToConnectVegaWallet();
|
||||
marketsPage.clickConnectVegaWallet();
|
||||
vegaWallet.openVegaWalletConnectDialog();
|
||||
vegaWallet.clickConnectVegaWallet();
|
||||
});
|
||||
|
||||
Then('wallet not running error message is displayed', () => {
|
||||
marketsPage.validateWalletNotRunningError();
|
||||
vegaWallet.validateWalletNotRunningError();
|
||||
});
|
||||
|
||||
Then('wallet field validation errors are shown', () => {
|
||||
marketsPage.validateWalletErrorFieldsDisplayed();
|
||||
vegaWallet.validateWalletErrorFieldsDisplayed();
|
||||
});
|
||||
|
@ -1,54 +0,0 @@
|
||||
import { Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
|
||||
import DealTicketPage from '../pages/deal-ticket-page';
|
||||
const dealTicketPage = new DealTicketPage();
|
||||
|
||||
When('place a buy {string} market order', (orderType) => {
|
||||
dealTicketPage.placeMarketOrder(true, 100, orderType);
|
||||
dealTicketPage.clickPlaceOrder();
|
||||
});
|
||||
|
||||
When('place a sell {string} market order', (orderType) => {
|
||||
dealTicketPage.placeMarketOrder(false, 100, orderType);
|
||||
dealTicketPage.clickPlaceOrder();
|
||||
});
|
||||
|
||||
When('place a buy {string} limit order', (limitOrderType) => {
|
||||
dealTicketPage.placeLimitOrder(true, 100, 2000, limitOrderType);
|
||||
dealTicketPage.clickPlaceOrder();
|
||||
});
|
||||
|
||||
When('place a sell {string} limit order', (limitOrderType) => {
|
||||
dealTicketPage.placeLimitOrder(false, 100, 2000, limitOrderType);
|
||||
dealTicketPage.clickPlaceOrder();
|
||||
});
|
||||
|
||||
When('place a buy {string} market order with amount of 0', (orderType) => {
|
||||
dealTicketPage.placeMarketOrder(true, 0, orderType);
|
||||
dealTicketPage.clickPlaceOrder();
|
||||
});
|
||||
|
||||
Then('order request is sent', () => {
|
||||
if (Cypress.env('bypassPlacingOrders' != true)) {
|
||||
dealTicketPage.verifyOrderRequestSent();
|
||||
}
|
||||
});
|
||||
|
||||
Then('error message for insufficient funds is displayed', () => {
|
||||
dealTicketPage.verifyOrderFailedInsufficientFunds();
|
||||
});
|
||||
|
||||
Then('place order button is disabled', () => {
|
||||
dealTicketPage.verifyPlaceOrderBtnDisabled();
|
||||
});
|
||||
|
||||
Then('{string} error is shown', (errorMsg) => {
|
||||
dealTicketPage.verifySubmitBtnErrorText(errorMsg);
|
||||
});
|
||||
|
||||
Then(
|
||||
'Order rejected by wallet error shown containing text {string}',
|
||||
(expectedError) => {
|
||||
dealTicketPage.verifyOrderRejected(expectedError);
|
||||
}
|
||||
);
|
@ -1,23 +1,47 @@
|
||||
import { When, Then } from 'cypress-cucumber-preprocessor/steps';
|
||||
import { And, Given, Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
import { hasOperationName } from '..';
|
||||
import MarketsPage from '../pages/markets-page';
|
||||
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
|
||||
import { generateMarkets } from '../../../../../libs/market-list/src/__tests__/generate-markets';
|
||||
|
||||
const marketsPage = new MarketsPage();
|
||||
|
||||
When('I click on market for {string}', (marketText) => {
|
||||
marketsPage.clickOnMarket(marketText);
|
||||
});
|
||||
|
||||
When('I click on active market', () => {
|
||||
if (Cypress.env('bypassPlacingOrders' != true)) {
|
||||
marketsPage.clickOnMarket('Active');
|
||||
} else {
|
||||
marketsPage.clickOnTopMarketRow();
|
||||
const mockMarkets = () => {
|
||||
cy.mockGQL('Markets', (req) => {
|
||||
if (hasOperationName(req, 'Markets')) {
|
||||
req.reply({
|
||||
body: { data: generateMarkets() },
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mockMarkets();
|
||||
});
|
||||
|
||||
When('I click on suspended market', () => {
|
||||
marketsPage.clickOnMarket('Suspended');
|
||||
Then('I navigate to markets page', () => {
|
||||
marketsPage.navigateToMarkets();
|
||||
});
|
||||
|
||||
Then('the market table is displayed', () => {
|
||||
Given('I am on the markets page', () => {
|
||||
cy.visit('/markets');
|
||||
cy.wait('@Markets');
|
||||
});
|
||||
|
||||
Then('I can view markets', () => {
|
||||
cy.wait('@Markets');
|
||||
marketsPage.validateMarketsAreDisplayed();
|
||||
});
|
||||
|
||||
And('the market table is displayed', () => {
|
||||
marketsPage.validateMarketTableDisplayed();
|
||||
});
|
||||
|
||||
When('I click on an active market', () => {
|
||||
marketsPage.clickOnMarket('Active');
|
||||
});
|
||||
|
||||
When('I click on a suspended market', () => {
|
||||
marketsPage.clickOnMarket('Suspended');
|
||||
});
|
||||
|
@ -0,0 +1,8 @@
|
||||
import { Then } from 'cypress-cucumber-preprocessor/steps';
|
||||
import PortfolioPage from '../pages/portfolio-page';
|
||||
|
||||
const portfolioPage = new PortfolioPage();
|
||||
|
||||
Then('I navigate to portfolio page', () => {
|
||||
portfolioPage.navigateToPortfolio();
|
||||
});
|
@ -0,0 +1,68 @@
|
||||
import { Given } from 'cypress-cucumber-preprocessor/steps';
|
||||
import { hasOperationName } from '..';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
/* eslint-disable @nrwl/nx/enforce-module-boundaries */
|
||||
import { generateTrades } from '../../../../../libs/trades/src/__tests__';
|
||||
import {
|
||||
generateChart,
|
||||
generateCandles,
|
||||
} from '../../../../../libs/chart/src/__tests__';
|
||||
import { generateDealTicketQuery } from '../../../../../libs/deal-ticket/src/__tests__';
|
||||
import { generateMarket } from '../../../../trading/pages/markets/__tests__';
|
||||
/* eslint-enable @nrwl/nx/enforce-module-boundaries */
|
||||
|
||||
const mockMarket = (state) => {
|
||||
cy.mockGQL('Market', (req) => {
|
||||
if (hasOperationName(req, 'Market')) {
|
||||
req.reply({
|
||||
body: {
|
||||
data: generateMarket({
|
||||
market: {
|
||||
name: `${state.toUpperCase()} MARKET`,
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (hasOperationName(req, 'DealTicketQuery')) {
|
||||
req.reply({
|
||||
body: { data: generateDealTicketQuery({ market: { state } }) },
|
||||
});
|
||||
}
|
||||
|
||||
if (hasOperationName(req, 'Trades')) {
|
||||
req.reply({
|
||||
body: { data: generateTrades() },
|
||||
});
|
||||
}
|
||||
|
||||
if (hasOperationName(req, 'Chart')) {
|
||||
req.reply({
|
||||
body: { data: generateChart() },
|
||||
});
|
||||
}
|
||||
|
||||
if (hasOperationName(req, 'Candles')) {
|
||||
req.reply({
|
||||
body: { data: generateCandles() },
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Given('I am on the trading page for an active market', () => {
|
||||
mockMarket(MarketState.Active);
|
||||
|
||||
cy.visit('/markets/market-id');
|
||||
cy.wait('@Market');
|
||||
cy.contains('Market: ACTIVE MARKET');
|
||||
});
|
||||
|
||||
Given('I am on the trading page for a suspended market', () => {
|
||||
mockMarket(MarketState.Suspended);
|
||||
|
||||
cy.visit('/markets/market-id');
|
||||
cy.wait('@Market');
|
||||
cy.contains('Market: SUSPENDED MARKET');
|
||||
});
|
@ -0,0 +1,30 @@
|
||||
import { When } from 'cypress-cucumber-preprocessor/steps';
|
||||
import VegaWallet from '../vega-wallet';
|
||||
|
||||
const vegaWallet = new VegaWallet();
|
||||
|
||||
beforeEach(() => {
|
||||
// The two important values here are the signature.value and the From.Pubkey.
|
||||
// From.PubKey is the first public key in the UI_Trading_Test wallet. We assert that the returned pubkey matches
|
||||
// what is used to sign the transaction
|
||||
// The tx.signature.value isn't currently used in any tests but the value returned is used to create IDs objects such
|
||||
// as orders, if its invalid an erro will be thrown
|
||||
cy.mockVegaCommandSync({
|
||||
txHash: 'test-tx-hash',
|
||||
tx: {
|
||||
signature: {
|
||||
value:
|
||||
'd86138bba739bbc1069b3dc975d20b3a1517c2b9bdd401c70eeb1a0ecbc502ec268cf3129824841178b8b506b0b7d650c76644dbd96f524a6cb2158fb7121800',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
When('I connect to Vega Wallet', () => {
|
||||
vegaWallet.openVegaWalletConnectDialog();
|
||||
vegaWallet.fillInWalletForm(
|
||||
'UI_Trading_Test',
|
||||
Cypress.env('tradingWalletPassphrase')
|
||||
);
|
||||
vegaWallet.clickConnectVegaWallet();
|
||||
});
|
@ -1,5 +1,4 @@
|
||||
import BasePage from './base-page';
|
||||
export default class DealTicketPage extends BasePage {
|
||||
export default class DealTicket {
|
||||
marketOrderType = 'order-type-TYPE_MARKET';
|
||||
limitOrderType = 'order-type-TYPE_LIMIT';
|
||||
buyOrder = 'order-side-SIDE_BUY';
|
||||
@ -53,8 +52,7 @@ export default class DealTicketPage extends BasePage {
|
||||
);
|
||||
cy.getByTestId(this.orderTransactionHash)
|
||||
.invoke('text')
|
||||
.should('contain', 'Tx hash: ')
|
||||
.and('have.length.above', 64);
|
||||
.should('contain', 'Tx hash: test-tx-hash');
|
||||
}
|
||||
|
||||
verifyOrderFailedInsufficientFunds() {
|
||||
@ -65,9 +63,8 @@ export default class DealTicketPage extends BasePage {
|
||||
}
|
||||
|
||||
clickPlaceOrder() {
|
||||
if (Cypress.env('bypassPlacingOrders' != true)) {
|
||||
cy.getByTestId(this.placeOrderBtn).click();
|
||||
}
|
||||
cy.contains('Awaiting network confirmation');
|
||||
}
|
||||
|
||||
verifyPlaceOrderBtnDisabled() {
|
||||
@ -75,7 +72,10 @@ export default class DealTicketPage extends BasePage {
|
||||
}
|
||||
|
||||
verifySubmitBtnErrorText(expectedText) {
|
||||
cy.getByTestId(this.inputError).should('have.text', expectedText);
|
||||
cy.getByTestId('dealticket-error-message').should(
|
||||
'have.text',
|
||||
expectedText
|
||||
);
|
||||
}
|
||||
|
||||
verifyOrderRejected(errorMsg) {
|
43
apps/trading-e2e/src/support/vega-wallet/index.js
Normal file
43
apps/trading-e2e/src/support/vega-wallet/index.js
Normal file
@ -0,0 +1,43 @@
|
||||
export default class VegaWallet {
|
||||
connectVegaBtn = 'connect-vega-wallet';
|
||||
walletConnectors = 'connectors-list';
|
||||
walletForm = 'rest-connector-form';
|
||||
walletInputError = 'input-wallet-error';
|
||||
walletFormError = 'form-error';
|
||||
inputError = 'input-error-text';
|
||||
|
||||
openVegaWalletConnectDialog() {
|
||||
cy.getByTestId(this.connectVegaBtn).click();
|
||||
cy.contains('Connects using REST to a running Vega wallet service');
|
||||
cy.getByTestId(this.walletConnectors).find('button').click();
|
||||
}
|
||||
|
||||
fillInWalletForm(walletName, walletPassphrase) {
|
||||
cy.getByTestId(this.walletForm)
|
||||
.find('#wallet')
|
||||
.click({ force: true })
|
||||
.type(walletName);
|
||||
cy.getByTestId(this.walletForm)
|
||||
.find('#passphrase')
|
||||
.click({ force: true })
|
||||
.type(walletPassphrase);
|
||||
}
|
||||
|
||||
clickConnectVegaWallet() {
|
||||
cy.getByTestId(this.walletForm)
|
||||
.find('button[type=submit]')
|
||||
.click({ force: true });
|
||||
}
|
||||
|
||||
validateWalletNotRunningError() {
|
||||
cy.getByTestId(this.walletFormError).should(
|
||||
'have.text',
|
||||
'Authentication failed'
|
||||
);
|
||||
}
|
||||
|
||||
validateWalletErrorFieldsDisplayed() {
|
||||
cy.getByTestId(this.walletInputError).should('have.text', 'Required');
|
||||
cy.getByTestId(this.inputError).should('have.text', 'Required');
|
||||
}
|
||||
}
|
@ -4,7 +4,15 @@
|
||||
"sourceMap": false,
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"allowJs": true,
|
||||
"types": ["cypress", "node"]
|
||||
"types": ["cypress", "node"],
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.js"]
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ function VegaTradingApp({ Component, pageProps }: AppProps) {
|
||||
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
|
||||
</div>
|
||||
</div>
|
||||
<main>
|
||||
<main data-testid={pageProps.page}>
|
||||
<Component {...pageProps} />
|
||||
</main>
|
||||
<VegaConnectDialog
|
||||
|
@ -22,4 +22,8 @@ export function Index() {
|
||||
);
|
||||
}
|
||||
|
||||
Index.getInitialProps = () => ({
|
||||
page: 'home',
|
||||
});
|
||||
|
||||
export default Index;
|
||||
|
@ -60,6 +60,10 @@ const MarketPage = () => {
|
||||
);
|
||||
};
|
||||
|
||||
MarketPage.getInitialProps = () => ({
|
||||
page: 'market',
|
||||
});
|
||||
|
||||
export default MarketPage;
|
||||
|
||||
const useWindowSize = () => {
|
||||
|
15
apps/trading/pages/markets/__tests__/generate-market.ts
Normal file
15
apps/trading/pages/markets/__tests__/generate-market.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { Market } from '../__generated__/Market';
|
||||
|
||||
export const generateMarket = (override?: PartialDeep<Market>): Market => {
|
||||
const defaultResult = {
|
||||
market: {
|
||||
id: 'market-id',
|
||||
name: 'MARKET NAME',
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
1
apps/trading/pages/markets/__tests__/index.ts
Normal file
1
apps/trading/pages/markets/__tests__/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './generate-market';
|
@ -4,4 +4,8 @@ const Markets = () => {
|
||||
return <MarketsContainer />;
|
||||
};
|
||||
|
||||
Markets.getInitialProps = () => ({
|
||||
page: 'markets',
|
||||
});
|
||||
|
||||
export default Markets;
|
||||
|
@ -31,4 +31,8 @@ const Deposit = () => {
|
||||
);
|
||||
};
|
||||
|
||||
Deposit.getInitialProps = () => ({
|
||||
page: 'deposit',
|
||||
});
|
||||
|
||||
export default Deposit;
|
||||
|
@ -5,8 +5,8 @@ import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
const Portfolio = () => {
|
||||
const { keypair } = useVegaWallet();
|
||||
return (
|
||||
<div>
|
||||
<h1>{t('Portfolio')}</h1>
|
||||
<div className="p-24">
|
||||
<h1 className="text-h3 mb-12">{t('Portfolio')}</h1>
|
||||
{keypair && <p>{t(`Keypair: ${keypair.name} ${keypair.pub}`)}</p>}
|
||||
<div className="flex gap-4">
|
||||
<AnchorButton href="/portfolio/deposit">{t('Deposit')}</AnchorButton>
|
||||
@ -18,4 +18,8 @@ const Portfolio = () => {
|
||||
);
|
||||
};
|
||||
|
||||
Portfolio.getInitialProps = () => ({
|
||||
page: 'portfolio',
|
||||
});
|
||||
|
||||
export default Portfolio;
|
||||
|
56
libs/chart/src/__tests__/generate-candles.ts
Normal file
56
libs/chart/src/__tests__/generate-candles.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
Candles,
|
||||
Candles_market_candles,
|
||||
} from '../lib/__generated__/Candles';
|
||||
|
||||
export const generateCandles = (override?: PartialDeep<Candles>): Candles => {
|
||||
const candles: Candles_market_candles[] = [
|
||||
{
|
||||
datetime: '2022-04-06T09:15:00Z',
|
||||
high: '17481092',
|
||||
low: '17403651',
|
||||
open: '17458833',
|
||||
close: '17446470',
|
||||
volume: '82721',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{
|
||||
datetime: '2022-04-06T09:30:00Z',
|
||||
high: '17491202',
|
||||
low: '17361138',
|
||||
open: '17446470',
|
||||
close: '17367174',
|
||||
volume: '62637',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{
|
||||
datetime: '2022-04-06T09:45:00Z',
|
||||
high: '17424522',
|
||||
low: '17337719',
|
||||
open: '17367174',
|
||||
close: '17376455',
|
||||
volume: '60259',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
];
|
||||
const defaultResult = {
|
||||
market: {
|
||||
id: 'market-id',
|
||||
decimalPlaces: 5,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
id: '',
|
||||
name: 'Apple Monthly (30 Jun 2022)',
|
||||
code: 'AAPL.MF21',
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
candles,
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
return merge(defaultResult, override);
|
||||
};
|
27
libs/chart/src/__tests__/generate-chart.ts
Normal file
27
libs/chart/src/__tests__/generate-chart.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
Chart,
|
||||
Chart_market_data_priceMonitoringBounds,
|
||||
} from '../lib/__generated__/Chart';
|
||||
|
||||
export const generateChart = (override?: PartialDeep<Chart>): Chart => {
|
||||
const priceMonitoringBound: Chart_market_data_priceMonitoringBounds = {
|
||||
minValidPrice: '16256291',
|
||||
maxValidPrice: '18296869',
|
||||
referencePrice: '17247489',
|
||||
__typename: 'PriceMonitoringBounds',
|
||||
};
|
||||
const defaultResult = {
|
||||
market: {
|
||||
decimalPlaces: 5,
|
||||
data: {
|
||||
priceMonitoringBounds: [priceMonitoringBound],
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
2
libs/chart/src/__tests__/index.ts
Normal file
2
libs/chart/src/__tests__/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './generate-candles';
|
||||
export * from './generate-chart';
|
@ -1,5 +1,9 @@
|
||||
import { addGetTestIdcommand } from './lib/commands/get-by-test-id';
|
||||
import { addMockGQLCommand } from './lib/commands/mock-gql';
|
||||
import { addMockVegaWalletCommands } from './lib/commands/mock-vega-wallet';
|
||||
import { addSlackCommand } from './lib/commands/slack';
|
||||
|
||||
addGetTestIdcommand();
|
||||
addSlackCommand();
|
||||
addMockGQLCommand();
|
||||
addMockVegaWalletCommands();
|
||||
|
21
libs/cypress/src/lib/commands/mock-gql.ts
Normal file
21
libs/cypress/src/lib/commands/mock-gql.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import type { RouteHandler } from 'cypress/types/net-stubbing';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
declare namespace Cypress {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface Chainable<Subject> {
|
||||
mockGQL(alias: string, handler: RouteHandler): void;
|
||||
}
|
||||
}
|
||||
|
||||
export function addMockGQLCommand() {
|
||||
Cypress.Commands.add(
|
||||
// @ts-ignore - ignoring Cypress type error which gets resolved when Cypress uses the command
|
||||
'mockGQL',
|
||||
(alias: string, handler: RouteHandler) => {
|
||||
cy.intercept('POST', 'https://lb.testnet.vega.xyz/query', handler).as(
|
||||
alias
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
45
libs/cypress/src/lib/commands/mock-vega-wallet.ts
Normal file
45
libs/cypress/src/lib/commands/mock-vega-wallet.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { TransactionResponse } from '@vegaprotocol/vegawallet-service-api-client';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
declare namespace Cypress {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface Chainable<Subject> {
|
||||
mockVegaCommandSync(txHash: string, signature: string): void;
|
||||
}
|
||||
}
|
||||
|
||||
export function addMockVegaWalletCommands() {
|
||||
Cypress.Commands.add(
|
||||
// @ts-ignore - ignoring Cypress type error which gets resolved when Cypress uses the command
|
||||
'mockVegaCommandSync',
|
||||
(override?: PartialDeep<TransactionResponse>) => {
|
||||
const defaultTransactionResponse = {
|
||||
txHash: 'tx-hash',
|
||||
tx: {
|
||||
input_data:
|
||||
'CPe6vpiqsPqxDBDC1w7KPkoKQGE4Y2M0NjUwMjhiMGY4OTM4YTYzZTEzNDViYzM2ODc3ZWRmODg4MjNmOWU0ZmI4ZDRlN2VkMmFlMzAwNzA3ZTMYASABKAM4Ag==',
|
||||
signature: {
|
||||
// sig value needs to be 'real' so sigToId function doesn't error out
|
||||
value: 'signature',
|
||||
algo: 'vega/ed25519',
|
||||
version: 1,
|
||||
},
|
||||
From: {
|
||||
PubKey: Cypress.env('vegaPublicKey'),
|
||||
},
|
||||
version: 2,
|
||||
pow: {
|
||||
tid: '0CEEC2FDFDB5D68BC0C1E2640440E4AA11E49986CB2929E0F3572E16CB7DC59C',
|
||||
nonce: 23525,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
cy.intercept('POST', 'http://localhost:1789/api/v1/command/sync', {
|
||||
body: merge(defaultTransactionResponse, override),
|
||||
}).as('VegaCommandSync');
|
||||
}
|
||||
);
|
||||
}
|
@ -11,8 +11,13 @@
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
}
|
||||
|
37
libs/deal-ticket/src/__tests__/generate-deal-ticket-query.ts
Normal file
37
libs/deal-ticket/src/__tests__/generate-deal-ticket-query.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { DealTicketQuery } from '../__generated__/DealTicketQuery';
|
||||
|
||||
export const generateDealTicketQuery = (
|
||||
override?: PartialDeep<DealTicketQuery>
|
||||
): DealTicketQuery => {
|
||||
const defaultResult: DealTicketQuery = {
|
||||
market: {
|
||||
id: 'market-id',
|
||||
decimalPlaces: 2,
|
||||
state: MarketState.Active,
|
||||
tradingMode: MarketTradingMode.Continuous,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
quoteName: 'BTC',
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
depth: {
|
||||
__typename: 'MarketDepth',
|
||||
lastTrade: {
|
||||
__typename: 'Trade',
|
||||
price: '100',
|
||||
},
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
1
libs/deal-ticket/src/__tests__/index.ts
Normal file
1
libs/deal-ticket/src/__tests__/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './generate-deal-ticket-query';
|
@ -79,7 +79,11 @@ export const SubmitButton = ({
|
||||
>
|
||||
{transactionStatus === 'pending' ? t('Pending...') : t('Place order')}
|
||||
</Button>
|
||||
{invalidText && <InputError className="mb-8">{invalidText}</InputError>}
|
||||
{invalidText && (
|
||||
<InputError className="mb-8" data-testid="dealticket-error-message">
|
||||
{invalidText}
|
||||
</InputError>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
78
libs/market-list/src/__tests__/generate-markets.ts
Normal file
78
libs/market-list/src/__tests__/generate-markets.ts
Normal file
@ -0,0 +1,78 @@
|
||||
import merge from 'lodash/merge';
|
||||
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { Markets, Markets_markets } from '../lib/__generated__/Markets';
|
||||
|
||||
export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
const markets: Markets_markets[] = [
|
||||
{
|
||||
id: 'market-id',
|
||||
name: 'ACTIVE MARKET',
|
||||
decimalPlaces: 5,
|
||||
data: {
|
||||
market: {
|
||||
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
|
||||
state: MarketState.Active,
|
||||
tradingMode: MarketTradingMode.Continuous,
|
||||
__typename: 'Market',
|
||||
},
|
||||
bestBidPrice: '0',
|
||||
bestOfferPrice: '0',
|
||||
markPrice: '4612690058',
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'BTCUSD.MF21',
|
||||
product: {
|
||||
settlementAsset: {
|
||||
symbol: 'tDAI',
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
{
|
||||
id: 'test-market-suspended',
|
||||
name: 'SUSPENDED MARKET',
|
||||
decimalPlaces: 2,
|
||||
data: {
|
||||
market: {
|
||||
id: '34d95e10faa00c21d19d382d6d7e6fc9722a96985369f0caec041b0f44b775ed',
|
||||
state: MarketState.Suspended,
|
||||
tradingMode: MarketTradingMode.Continuous,
|
||||
__typename: 'Market',
|
||||
},
|
||||
bestBidPrice: '0',
|
||||
bestOfferPrice: '0',
|
||||
markPrice: '8441',
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'SOLUSD',
|
||||
product: {
|
||||
settlementAsset: {
|
||||
symbol: 'XYZalpha',
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
];
|
||||
const defaultResult = {
|
||||
markets,
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
53
libs/trades/src/__tests__/generate-trades.ts
Normal file
53
libs/trades/src/__tests__/generate-trades.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { Trades, Trades_market_trades } from '../lib/__generated__/Trades';
|
||||
|
||||
export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
||||
const trades: Trades_market_trades[] = [
|
||||
{
|
||||
id: 'FFFFBC80005C517A10ACF481F7E6893769471098E696D0CC407F18134044CB16',
|
||||
price: '17116898',
|
||||
size: '24',
|
||||
createdAt: '2022-04-06T16:19:42.692598951Z',
|
||||
market: {
|
||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||
decimalPlaces: 5,
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Trade',
|
||||
},
|
||||
{
|
||||
id: 'FFFFB91453AC8F26EDAC223E2FB6C4A61461B1837946B51D943D675FB94FDF72',
|
||||
price: '17209102',
|
||||
size: '7',
|
||||
createdAt: '2022-04-07T06:59:44.835686754Z',
|
||||
market: {
|
||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||
decimalPlaces: 5,
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Trade',
|
||||
},
|
||||
{
|
||||
id: 'FFFFAD1BF47AA2853E5C375B6B3A62375F62D5B10807583D32EF3119CC455CD1',
|
||||
price: '17106734',
|
||||
size: '18',
|
||||
createdAt: '2022-04-07T17:56:47.997938583Z',
|
||||
market: {
|
||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||
decimalPlaces: 5,
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Trade',
|
||||
},
|
||||
];
|
||||
const defaultResult = {
|
||||
market: {
|
||||
id: 'market-id',
|
||||
trades,
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
1
libs/trades/src/__tests__/index.ts
Normal file
1
libs/trades/src/__tests__/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './generate-trades';
|
@ -124,6 +124,7 @@
|
||||
"sass": "1.43.2",
|
||||
"storybook-addon-themes": "^6.1.0",
|
||||
"ts-jest": "27.0.5",
|
||||
"type-fest": "^2.12.2",
|
||||
"typescript": "~4.5.2",
|
||||
"url-loader": "^3.0.0"
|
||||
},
|
||||
|
@ -20171,6 +20171,11 @@ type-fest@^0.8.1:
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||
|
||||
type-fest@^2.12.2:
|
||||
version "2.12.2"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.2.tgz#80a53614e6b9b475eb9077472fb7498dc7aa51d0"
|
||||
integrity sha512-qt6ylCGpLjZ7AaODxbpyBZSs9fCI9SkL3Z9q2oxMBQhs/uyY+VD8jHA8ULCGmWQJlBgqvO3EJeAngOHD8zQCrQ==
|
||||
|
||||
type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
|
Loading…
Reference in New Issue
Block a user