Merge branch 'master' of github.com:vegaprotocol/frontend-monorepo
This commit is contained in:
commit
e5efa417a0
@ -1,16 +1,13 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
const setupNodeEvents = require('./src/plugins/index.js');
|
||||
|
||||
module.exports = defineConfig({
|
||||
projectId: 'et4snf',
|
||||
|
||||
e2e: {
|
||||
setupNodeEvents,
|
||||
baseUrl: 'http://localhost:3000',
|
||||
fileServerFolder: '.',
|
||||
fixturesFolder: false,
|
||||
specPattern: '**/*.feature',
|
||||
excludeSpecPattern: '**/*.js',
|
||||
specPattern: '**/*.cy.{js,jsx,ts,tsx}',
|
||||
modifyObstructiveCode: false,
|
||||
supportFile: './src/support/index.ts',
|
||||
video: true,
|
||||
|
@ -1,11 +0,0 @@
|
||||
Feature: Asset Page
|
||||
|
||||
Scenario: Navigate to Asset Page
|
||||
Given I am on the homepage
|
||||
When I navigate to the asset page
|
||||
Then asset page is correctly displayed
|
||||
|
||||
Scenario: Navigate to Asset Page using mobile
|
||||
Given I am on mobile and open the toggle menu
|
||||
When I navigate to the asset page
|
||||
Then asset page is correctly displayed
|
20
apps/explorer-e2e/src/integration/asset.cy.js
Normal file
20
apps/explorer-e2e/src/integration/asset.cy.js
Normal file
@ -0,0 +1,20 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
context('Asset page', function () {
|
||||
describe('Verify elements on page', function () {
|
||||
const assetsNavigation = 'a[href="/assets"]';
|
||||
const assetHeader = '[data-testid="asset-header"]';
|
||||
|
||||
it('Assets page is displayed', function () {
|
||||
cy.visit('/');
|
||||
cy.get(assetsNavigation).click();
|
||||
cy.common_validate_blocks_data_displayed(assetHeader);
|
||||
});
|
||||
|
||||
it('Assets page displayed in mobile', function () {
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.get(assetsNavigation).click();
|
||||
cy.common_validate_blocks_data_displayed(assetHeader);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,38 +0,0 @@
|
||||
Feature: Blocks Page
|
||||
|
||||
Scenario: Navigate to blocks page
|
||||
Given I am on the homepage
|
||||
When I navigate to the blocks page
|
||||
Then blocks page is correctly displayed
|
||||
|
||||
Scenario: Navigate to blocks page using mobile
|
||||
Given I am on mobile and open the toggle menu
|
||||
When I navigate to the blocks page
|
||||
Then blocks page is correctly displayed
|
||||
|
||||
Scenario: Navigate to block validator page
|
||||
Given I am on the homepage
|
||||
When I navigate to the blocks page
|
||||
And I click on top block
|
||||
Then validator block page is correctly displayed
|
||||
|
||||
Scenario: Navigate to previous block
|
||||
Given I am on the homepage
|
||||
When I navigate to the blocks page
|
||||
And I click on top block
|
||||
Then I am on the previous block when I click previous
|
||||
|
||||
Scenario: Previous button disabled on first block
|
||||
Given I am on the homepage
|
||||
When I navigate to the blocks page
|
||||
And jump to first block
|
||||
Then previous button is disabled
|
||||
And I am on the second block when I click next
|
||||
|
||||
# Skipping these tests for time being - since blockchain in capsule
|
||||
# is now too small to show historical data - re-enable once addressed
|
||||
# Scenario: Infinite scroll shows at least 300 new blocks
|
||||
# Given I am on the homepage
|
||||
# When I navigate to the blocks page
|
||||
# And I scroll down to the last block on the page
|
||||
# Then I can expect to see at least 100 blocks if i scroll 7 times
|
132
apps/explorer-e2e/src/integration/blocks.cy.js
Normal file
132
apps/explorer-e2e/src/integration/blocks.cy.js
Normal file
@ -0,0 +1,132 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
context('Blocks page', function () {
|
||||
before('visit token home page', function () {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
describe('Verify elements on page', function () {
|
||||
const blockNavigation = 'a[href="/blocks"]';
|
||||
const blockHeight = '[data-testid="block-height"]';
|
||||
const blockTime = '[data-testid="block-time"]';
|
||||
const blockHeader = '[data-testid="block-header"]';
|
||||
const previousBlockBtn = '[data-testid="previous-block"]';
|
||||
const infiniteScrollWrapper = '[data-testid="infinite-scroll-wrapper"]';
|
||||
|
||||
beforeEach('navigate to blocks page', function () {
|
||||
cy.get(blockNavigation).click();
|
||||
});
|
||||
|
||||
it('Blocks page is displayed', function () {
|
||||
validateBlocksDisplayed();
|
||||
});
|
||||
|
||||
it('Blocks page is displayed on mobile', function () {
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.get(blockNavigation).click();
|
||||
validateBlocksDisplayed();
|
||||
});
|
||||
|
||||
it('Block validator page is displayed', function () {
|
||||
waitForBlocksResponse();
|
||||
cy.get(blockHeight).eq(0).click();
|
||||
cy.get('[data-testid="block-validator"]').should('not.be.empty');
|
||||
cy.get(blockTime).should('not.be.empty');
|
||||
//TODO: Add assertion for transactions when txs are added
|
||||
});
|
||||
|
||||
it('Navigate to previous block', function () {
|
||||
waitForBlocksResponse();
|
||||
cy.get(blockHeight).eq(0).click();
|
||||
cy.get(blockHeader)
|
||||
.invoke('text')
|
||||
.then(($blockHeaderTxt) => {
|
||||
const blockHeight = parseInt($blockHeaderTxt.replace('BLOCK ', ''));
|
||||
cy.get(previousBlockBtn).click();
|
||||
cy.get(blockHeader)
|
||||
.invoke('text')
|
||||
.then(($newBlockHeaderTxt) => {
|
||||
const newBlockHeight = parseInt(
|
||||
$newBlockHeaderTxt.replace('BLOCK ', '')
|
||||
);
|
||||
expect(newBlockHeight).to.be.lessThan(blockHeight);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Previous button disabled on first block', function () {
|
||||
cy.get('[data-testid="block-input"]').type('1');
|
||||
cy.get('[data-testid="go-submit"]').click();
|
||||
cy.get(previousBlockBtn).find('button').should('be.disabled');
|
||||
cy.get(blockHeader)
|
||||
.invoke('text')
|
||||
.then(($blockHeaderTxt) => {
|
||||
const blockHeight = parseInt($blockHeaderTxt.replace('BLOCK ', ''));
|
||||
cy.get('[data-testid="next-block"]').click();
|
||||
cy.get(blockHeader)
|
||||
.invoke('text')
|
||||
.then(($newBlockHeaderTxt) => {
|
||||
const newBlockHeight = parseInt(
|
||||
$newBlockHeaderTxt.replace('BLOCK ', '')
|
||||
);
|
||||
expect(newBlockHeight).to.be.greaterThan(blockHeight);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Skipping these tests for time being - since blockchain in capsule is now too small to show historical data - re-enable once addressed
|
||||
it.skip('Infinite scroll shows at least 100 new blocks', function () {
|
||||
const expectedBlocks = 100;
|
||||
const scrollAttempts = 7;
|
||||
|
||||
waitForBlocksResponse();
|
||||
cy.get(infiniteScrollWrapper).children().scrollTo('bottom');
|
||||
|
||||
cy.intercept('*blockchain?maxHeight*').as('blockchain_load');
|
||||
cy.get(blockHeight)
|
||||
.last()
|
||||
.invoke('text')
|
||||
.then(($initialLastBlockHeight) => {
|
||||
for (let index = 0; index < scrollAttempts; index++) {
|
||||
cy.get(infiniteScrollWrapper)
|
||||
.children()
|
||||
.children()
|
||||
.invoke('css', 'height')
|
||||
.then((scrollTarget) => {
|
||||
cy.get(infiniteScrollWrapper)
|
||||
.children()
|
||||
.scrollTo(0, scrollTarget.toString(), { easing: 'linear' })
|
||||
.wait('@blockchain_load');
|
||||
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(50); // Need this as although network response has arrived it takes a few millisecs for the css height to expand
|
||||
});
|
||||
}
|
||||
|
||||
cy.get(blockHeight)
|
||||
.last()
|
||||
.invoke('text')
|
||||
.then(($lastBlockHeight) => {
|
||||
const totalBlocksLoadedSinceScrollBegan =
|
||||
parseInt($initialLastBlockHeight) - parseInt($lastBlockHeight);
|
||||
expect(totalBlocksLoadedSinceScrollBegan).to.be.at.least(
|
||||
expectedBlocks
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function waitForBlocksResponse() {
|
||||
cy.contains('Loading...').should('not.exist', { timeout: 18000 });
|
||||
}
|
||||
|
||||
function validateBlocksDisplayed() {
|
||||
waitForBlocksResponse();
|
||||
cy.get('[data-testid="block-row"]').should('have.length.above', 1);
|
||||
cy.get(blockHeight).first().should('not.be.empty');
|
||||
cy.get('[data-testid="num-txs"]').first().should('not.be.empty');
|
||||
cy.get('[data-testid="validator-link"]').first().should('not.be.empty');
|
||||
cy.get(blockTime).first().should('not.be.empty');
|
||||
}
|
||||
});
|
||||
});
|
@ -1,27 +0,0 @@
|
||||
Feature: Home page
|
||||
|
||||
Scenario: Stats page displayed correctly
|
||||
Given I am on the homepage
|
||||
Then the stats for deployed environment are correctly displayed
|
||||
|
||||
Scenario Outline: Succesfful search for specific id by <IdType>
|
||||
Given I am on the homepage
|
||||
When I search for '<Id>'
|
||||
Then I am redirected to page containing id '<Id>'
|
||||
|
||||
Examples:
|
||||
| IdType | Id |
|
||||
| Block Id | 973624 |
|
||||
| Tx Hash | 9ED3718AA8308E7E08EC588EE7AADAF49711D2138860D8914B4D81A2054D9FB8 |
|
||||
| Tx Id | 0x61DCCEBB955087F50D0B85382DAE138EDA9631BF1A4F92E563D528904AA38898 |
|
||||
|
||||
Scenario Outline: Error message displayed when invalid search by <invalidType>
|
||||
Given I am on the homepage
|
||||
When I search for '<Id>'
|
||||
Then search error message "<errorMessage>" is displayed
|
||||
|
||||
Examples:
|
||||
| invalidType | Id | errorMessage |
|
||||
| wrong string length | 9ED3718AA8308E7E08EC588EE7AADAF497D2138860D8914B4D81A2054D9FB8 | Something doesn't look right |
|
||||
| invalid hash | 9ED3718AA8308E7E08ECht8EE753DAF49711D2138860D8914B4D81A2054D9FB8 | Transaction is not hexadecimal |
|
||||
| empty search | | Search required |
|
141
apps/explorer-e2e/src/integration/home.cy.js
Normal file
141
apps/explorer-e2e/src/integration/home.cy.js
Normal file
@ -0,0 +1,141 @@
|
||||
context('Home Page', function () {
|
||||
before('visit home page', function () {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
describe('Stats page', function () {
|
||||
const statsValue = '[data-testid="stats-value"]';
|
||||
|
||||
it('Should show connected environment', function () {
|
||||
const deployedEnv = Cypress.env('environment').toUpperCase();
|
||||
cy.get('[data-testid="stats-environment"]').should(
|
||||
'have.text',
|
||||
`/ ${deployedEnv}`
|
||||
);
|
||||
});
|
||||
|
||||
it('should show connected environment stats', function () {
|
||||
const statTitles = {
|
||||
0: 'Status',
|
||||
1: 'Height',
|
||||
2: 'Validating nodes',
|
||||
3: 'Uptime',
|
||||
4: 'Total nodes',
|
||||
5: 'Inactive nodes',
|
||||
6: 'Total staked',
|
||||
7: 'Backlog',
|
||||
8: 'Trades / second',
|
||||
9: 'Orders / block',
|
||||
10: 'Orders / second',
|
||||
11: 'Transactions / block',
|
||||
12: 'Block time',
|
||||
13: 'Time',
|
||||
14: 'App',
|
||||
15: 'Tendermint',
|
||||
16: 'Up since',
|
||||
17: 'Chain ID',
|
||||
};
|
||||
|
||||
cy.get('[data-testid="stats-title"]')
|
||||
.each(($list, index) => {
|
||||
cy.wrap($list).should('have.text', statTitles[index]);
|
||||
})
|
||||
.then(($list) => {
|
||||
cy.wrap($list).should('have.length', 18);
|
||||
});
|
||||
|
||||
cy.get(statsValue).eq(0).should('have.text', 'CONNECTED');
|
||||
cy.get(statsValue).eq(1).should('not.be.empty');
|
||||
cy.get(statsValue).eq(2).should('have.text', '2');
|
||||
cy.get(statsValue)
|
||||
.eq(3)
|
||||
.invoke('text')
|
||||
.should('match', /\d+d \d+h \d+m \d+s/i);
|
||||
cy.get(statsValue).eq(4).should('have.text', '2');
|
||||
cy.get(statsValue).eq(5).should('have.text', '0');
|
||||
cy.get(statsValue).eq(6).should('have.text', '0.00');
|
||||
cy.get(statsValue).eq(7).should('have.text', '0');
|
||||
cy.get(statsValue).eq(8).should('have.text', '0');
|
||||
cy.get(statsValue).eq(9).should('have.text', '0');
|
||||
cy.get(statsValue).eq(10).should('have.text', '0');
|
||||
cy.get(statsValue).eq(11).should('not.be.empty');
|
||||
cy.get(statsValue).eq(12).should('not.be.empty');
|
||||
cy.get(statsValue).eq(13).should('not.be.empty');
|
||||
if (Cypress.env('NIGHTLY_RUN') != true) {
|
||||
cy.get(statsValue)
|
||||
.eq(14)
|
||||
.invoke('text')
|
||||
.should('match', /v\d+\.\d+\.\d+/i);
|
||||
}
|
||||
cy.get(statsValue)
|
||||
.eq(15)
|
||||
.invoke('text')
|
||||
.should('match', /\d+\.\d+\.\d+/i);
|
||||
cy.get(statsValue).eq(16).should('not.be.empty');
|
||||
cy.get(statsValue).eq(17).should('not.be.empty');
|
||||
});
|
||||
|
||||
it('Block height should be updating', function () {
|
||||
cy.get(statsValue)
|
||||
.eq(1)
|
||||
.invoke('text')
|
||||
.then((blockHeightTxt) => {
|
||||
cy.get(statsValue)
|
||||
.eq(1)
|
||||
.invoke('text')
|
||||
.should((newBlockHeightTxt) => {
|
||||
expect(blockHeightTxt).not.to.eq(newBlockHeightTxt);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Search bar', function () {
|
||||
it('Successful search for specific id by block id', function () {
|
||||
const blockId = '973624';
|
||||
search(blockId);
|
||||
cy.url().should('include', blockId);
|
||||
});
|
||||
|
||||
it('Successful search for specific id by tx hash', function () {
|
||||
const txHash =
|
||||
'9ED3718AA8308E7E08EC588EE7AADAF49711D2138860D8914B4D81A2054D9FB8';
|
||||
search(txHash);
|
||||
cy.url().should('include', txHash);
|
||||
});
|
||||
|
||||
it('Successful search for specific id by tx id', function () {
|
||||
const txId =
|
||||
'0x61DCCEBB955087F50D0B85382DAE138EDA9631BF1A4F92E563D528904AA38898';
|
||||
search(txId);
|
||||
cy.url().should('include', txId);
|
||||
});
|
||||
|
||||
it('Error message displayed when invalid search by wrong string length', function () {
|
||||
search('9ED3718AA8308E7E08EC588EE7AADAF497D2138860D8914B4D81A2054D9FB8');
|
||||
validateSearchError("Something doesn't look right");
|
||||
});
|
||||
|
||||
it('Error message displayed when invalid search by invalid hash', function () {
|
||||
search(
|
||||
'9ED3718AA8308E7E08ECht8EE753DAF49711D2138860D8914B4D81A2054D9FB8'
|
||||
);
|
||||
validateSearchError('Transaction is not hexadecimal');
|
||||
});
|
||||
|
||||
it('Error message displayed when searching empty field', function () {
|
||||
cy.get('[data-testid="search"]').clear();
|
||||
cy.get('[data-testid="search-button"]').click();
|
||||
validateSearchError('Search required');
|
||||
});
|
||||
|
||||
function search(searchTxt) {
|
||||
cy.get('[data-testid="search"]').clear().type(searchTxt);
|
||||
cy.get('[data-testid="search-button"]').click();
|
||||
}
|
||||
|
||||
function validateSearchError(expectedError) {
|
||||
cy.get('[data-testid="search-error"]').should('have.text', expectedError);
|
||||
}
|
||||
});
|
||||
});
|
21
apps/explorer-e2e/src/integration/market.cy.js
Normal file
21
apps/explorer-e2e/src/integration/market.cy.js
Normal file
@ -0,0 +1,21 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
//Tests set to skip until market bug for capsule checkpoint is fixed
|
||||
context.skip('Market page', function () {
|
||||
describe('Verify elements on page', function () {
|
||||
const marketHeaders = '[data-testid="markets-header"]';
|
||||
const marketNavigation = 'a[href="/markets"]';
|
||||
|
||||
it('Markets page is displayed', function () {
|
||||
cy.visit('/');
|
||||
cy.get(marketNavigation).click();
|
||||
cy.common_validate_blocks_data_displayed(marketHeaders);
|
||||
});
|
||||
|
||||
it('Markets page displayed on mobile', function () {
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.get(marketNavigation).click();
|
||||
cy.common_validate_blocks_data_displayed(marketHeaders);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,14 +0,0 @@
|
||||
@todo
|
||||
Feature: Markets Page
|
||||
|
||||
@todo - Needs markets in capsule state
|
||||
Scenario: Navigate to markets page
|
||||
Given I am on the homepage
|
||||
When I navigate to the markets page
|
||||
Then markets page is correctly displayed
|
||||
|
||||
@todo
|
||||
Scenario: Navigate to markets page using mobile
|
||||
Given I am on mobile and open the toggle menu
|
||||
When I navigate to the markets page
|
||||
Then markets page is correctly displayed
|
@ -1,11 +0,0 @@
|
||||
Feature: Network parameters Page
|
||||
|
||||
Scenario: Navigate to network parameters page
|
||||
Given I am on the homepage
|
||||
When I navigate to network parameters page
|
||||
Then network parameters page is correctly displayed
|
||||
|
||||
Scenario: Navigate to network parameters page using mobile
|
||||
Given I am on mobile and open the toggle menu
|
||||
When I navigate to network parameters page
|
||||
Then network parameters page is correctly displayed
|
35
apps/explorer-e2e/src/integration/network.cy.js
Normal file
35
apps/explorer-e2e/src/integration/network.cy.js
Normal file
@ -0,0 +1,35 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
context('Network parameters page', function () {
|
||||
before('visit token home page', function () {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
describe('Verify elements on page', function () {
|
||||
const networkParametersNavigation = 'a[href="/network-parameters"]';
|
||||
|
||||
beforeEach('Navigate to network parameter page', function () {
|
||||
cy.get(networkParametersNavigation).click();
|
||||
});
|
||||
|
||||
it('Network paremeter page is displayed', function () {
|
||||
verifyNetworkParametersPageDisplayed();
|
||||
});
|
||||
|
||||
it('Network parameter page displayed on mobile', function () {
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.get(networkParametersNavigation).click();
|
||||
verifyNetworkParametersPageDisplayed();
|
||||
});
|
||||
});
|
||||
|
||||
function verifyNetworkParametersPageDisplayed() {
|
||||
cy.get('[data-testid="network-param-header"]').should(
|
||||
'have.text',
|
||||
'Network Parameters'
|
||||
);
|
||||
cy.common_verify_json_parameters(18);
|
||||
cy.common_verify_json_string_values(6);
|
||||
cy.common_verify_json_int_values(7);
|
||||
}
|
||||
});
|
@ -1,21 +0,0 @@
|
||||
@ignore
|
||||
# tendermint times out getting txs on testnet atm
|
||||
Feature: Transactions Page
|
||||
|
||||
Scenario: Navigate to transactions page
|
||||
Given I am on the homepage
|
||||
When I navigate to the transactions page
|
||||
Then transactions page is correctly displayed
|
||||
|
||||
Scenario: Navigate to transaction details page
|
||||
Given I am on the homepage
|
||||
When I navigate to the transactions page
|
||||
And I click on the top transaction
|
||||
Then transaction details are displayed
|
||||
|
||||
Scenario: Navigate to transactions page using mobile
|
||||
Given I am on mobile and open the toggle menu
|
||||
When I navigate to the transactions page
|
||||
Then transactions page is correctly displayed
|
||||
When I click on the top transaction
|
||||
Then transaction details are displayed
|
87
apps/explorer-e2e/src/integration/transactions.cy.js
Normal file
87
apps/explorer-e2e/src/integration/transactions.cy.js
Normal file
@ -0,0 +1,87 @@
|
||||
//Tests set to skip until transactions are generated after capsule start up
|
||||
context.skip('Transactions page', function () {
|
||||
before('visit token home page', function () {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
describe('Verify elements on page', function () {
|
||||
const transactionNavigation = 'a[href="/txs"]';
|
||||
const transactionRow = 'transaction-row';
|
||||
const txHash = 'hash';
|
||||
|
||||
beforeEach('Navigate to transactions page', function () {
|
||||
cy.get(transactionNavigation).click();
|
||||
});
|
||||
|
||||
it('transactions are displayed', function () {
|
||||
cy.get(transactionRow).should('have.length.above', 1);
|
||||
});
|
||||
|
||||
it('transactions details page is displayed', function () {
|
||||
clickTopTransaction();
|
||||
validateTxDetailsAreDisplayed();
|
||||
});
|
||||
|
||||
it('transactions details page is displayed in mobile', function () {
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.get(transactionNavigation).click();
|
||||
clickTopTransaction();
|
||||
validateTxDetailsAreDisplayed();
|
||||
});
|
||||
|
||||
function clickTopTransaction() {
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(1000); // Wait for transactions to load if there are any
|
||||
cy.get('body').then(($body) => {
|
||||
if ($body.find(transactionRow).length) {
|
||||
cy.get(transactionRow)
|
||||
.first()
|
||||
.find('a')
|
||||
.first()
|
||||
.click({ force: true });
|
||||
} else {
|
||||
cy.slack('Unable to find any transactions on page');
|
||||
cy.screenshot();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function validateTxDetailsAreDisplayed() {
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(1000); // Wait for transactions to load if there are any
|
||||
cy.get('body').then(($body) => {
|
||||
if ($body.find(txHash).length) {
|
||||
cy.get(txHash).invoke('text').should('have.length', 64);
|
||||
cy.get('submitted-by')
|
||||
.find('a')
|
||||
.then(($address) => {
|
||||
cy.wrap($address).should('have.attr', 'href');
|
||||
cy.wrap($address).invoke('text').should('have.length', 66);
|
||||
});
|
||||
cy.get('block').should('not.be.empty');
|
||||
cy.get('encoded-tnx').should('not.be.empty');
|
||||
cy.get('tx-type')
|
||||
.should('not.be.empty')
|
||||
.invoke('text')
|
||||
.then((txTypeTxt) => {
|
||||
if (txTypeTxt == 'Order Submission') {
|
||||
cy.get('.hljs-attr')
|
||||
.should('have.length.at.least', 8)
|
||||
.each(($propertyName) => {
|
||||
cy.wrap($propertyName).should('not.be.empty');
|
||||
});
|
||||
cy.get('.hljs-string')
|
||||
.should('have.length.at.least', 8)
|
||||
.each(($propertyValue) => {
|
||||
cy.wrap($propertyValue).should('not.be.empty');
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cy.slack('Unable to find any transactions on page');
|
||||
cy.screenshot();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
28
apps/explorer-e2e/src/integration/validator.cy.js
Normal file
28
apps/explorer-e2e/src/integration/validator.cy.js
Normal file
@ -0,0 +1,28 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
context('Validator page', function () {
|
||||
describe('Verify elements on page', function () {
|
||||
const validatorNavigation = 'a[href="/validators"]';
|
||||
|
||||
it('Validator page is displayed', function () {
|
||||
cy.visit('/');
|
||||
cy.get(validatorNavigation).click();
|
||||
validateValidatorsDisplayed();
|
||||
});
|
||||
|
||||
it('Validator page is displayed on mobile', function () {
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.get(validatorNavigation).click();
|
||||
validateValidatorsDisplayed();
|
||||
});
|
||||
|
||||
function validateValidatorsDisplayed() {
|
||||
cy.get('[data-testid="tendermint-header"]').should(
|
||||
'have.text',
|
||||
'Tendermint data'
|
||||
);
|
||||
cy.get('[data-testid="vega-header"]').should('have.text', 'Vega data');
|
||||
cy.get('[data-testid="vega-data"]').should('not.be.empty');
|
||||
}
|
||||
});
|
||||
});
|
@ -1,11 +0,0 @@
|
||||
Feature: Validators Page
|
||||
|
||||
Scenario: Navigate to validators page
|
||||
Given I am on the homepage
|
||||
When I navigate to the validators page
|
||||
Then validators page is correctly displayed
|
||||
|
||||
Scenario: Navigate to validators page using mobile
|
||||
Given I am on mobile and open the toggle menu
|
||||
When I navigate to the validators page
|
||||
Then validators page is correctly displayed
|
@ -1,75 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const webpackPreprocessor = require('@cypress/webpack-preprocessor');
|
||||
const webpack = require('webpack');
|
||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
const nodeExternals = require('webpack-node-externals');
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
module.exports = (on, config) => {
|
||||
on(
|
||||
'file:preprocessor',
|
||||
webpackPreprocessor({
|
||||
webpackOptions: {
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx'],
|
||||
plugins: [
|
||||
new TsconfigPathsPlugin({
|
||||
configFile: config.env.tsConfig,
|
||||
extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx'],
|
||||
}),
|
||||
],
|
||||
fallback: {
|
||||
path: require.resolve('path-browserify'),
|
||||
},
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.([jt])sx?$/,
|
||||
loader: 'ts-loader',
|
||||
exclude: [/node_modules/],
|
||||
options: {
|
||||
configFile: config.env.tsConfig,
|
||||
// https://github.com/TypeStrong/ts-loader/pull/685
|
||||
experimentalWatchApi: true,
|
||||
transpileOnly: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.feature$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'cypress-cucumber-preprocessor/loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.features$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'cypress-cucumber-preprocessor/lib/featuresLoader',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: {
|
||||
enabled: true,
|
||||
configFile: config.env.tsConfig,
|
||||
},
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
process: 'process/browser',
|
||||
}),
|
||||
],
|
||||
externals: [nodeExternals()],
|
||||
},
|
||||
})
|
||||
);
|
||||
};
|
53
apps/explorer-e2e/src/support/common.functions.js
Normal file
53
apps/explorer-e2e/src/support/common.functions.js
Normal file
@ -0,0 +1,53 @@
|
||||
Cypress.Commands.add(
|
||||
'common_validate_blocks_data_displayed',
|
||||
function (headerTestId) {
|
||||
cy.get(headerTestId).then(($assetHeaders) => {
|
||||
const headersLength = Number($assetHeaders.length);
|
||||
|
||||
cy.wrap($assetHeaders).each(($header) => {
|
||||
expect($header).to.not.be.empty;
|
||||
});
|
||||
|
||||
cy.get('.language-json')
|
||||
.each(($asset) => {
|
||||
expect($asset).to.not.be.empty;
|
||||
})
|
||||
.then(($list) => {
|
||||
expect($list).to.have.length(headersLength);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add('common_switch_to_mobile_and_click_toggle', function () {
|
||||
cy.viewport('iphone-x');
|
||||
cy.visit('/');
|
||||
cy.get('[data-testid="open-menu"]').click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('common_verify_json_parameters', function (expectedNum) {
|
||||
cy.get('.hljs-attr')
|
||||
.should('have.length.at.least', expectedNum)
|
||||
.each(($paramName) => {
|
||||
cy.wrap($paramName).should('not.be.empty');
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'common_verify_json_string_values',
|
||||
function (expectedNum) {
|
||||
cy.get('.hljs-string')
|
||||
.should('have.length.at.least', expectedNum)
|
||||
.each(($paramValue) => {
|
||||
cy.wrap($paramValue).should('not.be.empty');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add('common_verify_json_int_values', function (expectedNum) {
|
||||
cy.get('.hljs-number')
|
||||
.should('have.length.at.least', expectedNum)
|
||||
.each(($paramValue) => {
|
||||
cy.wrap($paramValue).should('not.be.empty');
|
||||
});
|
||||
});
|
2
apps/explorer-e2e/src/support/index.d.ts
vendored
Normal file
2
apps/explorer-e2e/src/support/index.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
// type definitions for Cypress object "cy"
|
||||
/// <reference types="cypress" />
|
@ -1,9 +0,0 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class AssetsPage extends BasePage {
|
||||
assetHeader = 'asset-header';
|
||||
|
||||
validateAssetsDisplayed() {
|
||||
this.validateBlockDataDisplayed(this.assetHeader);
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
export default class BasePage {
|
||||
transactionsUrl = '/txs';
|
||||
blocksUrl = '/blocks';
|
||||
partiesUrl = '/parties';
|
||||
assetsUrl = '/assets';
|
||||
genesisUrl = '/genesis';
|
||||
governanceUrl = '/governance';
|
||||
marketsUrl = '/markets';
|
||||
networkParametersUrl = '/network-parameters';
|
||||
validatorsUrl = '/validators';
|
||||
blockExplorerHeader = 'explorer-header';
|
||||
searchField = 'search';
|
||||
searchButton = 'search-button';
|
||||
searchError = 'search-error';
|
||||
openMobileMenuBtn = 'open-menu';
|
||||
|
||||
navigateToTxs() {
|
||||
cy.get(`a[href='${this.transactionsUrl}']`).click();
|
||||
}
|
||||
|
||||
navigateToBlocks() {
|
||||
cy.get(`a[href='${this.blocksUrl}']`).click();
|
||||
}
|
||||
|
||||
navigateToParties() {
|
||||
cy.get(`a[href='${this.partiesUrl}']`).click();
|
||||
}
|
||||
|
||||
navigateToAssets() {
|
||||
cy.get(`a[href*='${this.assetsUrl}']`).click();
|
||||
}
|
||||
|
||||
navigateToGenesis() {
|
||||
cy.get(`a[href='${this.genesisUrl}']`).click();
|
||||
}
|
||||
|
||||
navigateToGovernance() {
|
||||
cy.get(`a[href='${this.governanceUrl}']`).click();
|
||||
}
|
||||
|
||||
navigateToMarkets() {
|
||||
cy.get(`a[href='${this.marketsUrl}']`).click();
|
||||
}
|
||||
|
||||
navigateToNetworkParameters() {
|
||||
cy.get(`a[href='${this.networkParametersUrl}']`).click();
|
||||
}
|
||||
|
||||
navigateToValidators() {
|
||||
cy.get(`a[href='${this.validatorsUrl}']`).click();
|
||||
}
|
||||
|
||||
search(searchText: string) {
|
||||
if (searchText) {
|
||||
cy.getByTestId(this.searchField).type(searchText);
|
||||
}
|
||||
}
|
||||
|
||||
clickSearch() {
|
||||
cy.getByTestId(this.searchButton).click();
|
||||
}
|
||||
|
||||
clickOnToggle() {
|
||||
cy.getByTestId(this.openMobileMenuBtn).click({ force: true });
|
||||
}
|
||||
|
||||
validateUrl(expectedUrl: string) {
|
||||
cy.url().should('include', expectedUrl);
|
||||
}
|
||||
|
||||
validateSearchDisplayed() {
|
||||
cy.getByTestId(this.blockExplorerHeader).should(
|
||||
'have.text',
|
||||
'Vega Explorer'
|
||||
);
|
||||
cy.getByTestId(this.searchField).should('be.visible');
|
||||
}
|
||||
|
||||
validateSearchErrorDisplayed(errorMessage: string) {
|
||||
cy.getByTestId(this.searchError).should('have.text', errorMessage);
|
||||
}
|
||||
|
||||
validateBlockDataDisplayed(headerTestId: string) {
|
||||
cy.getByTestId(headerTestId).then(($assetHeaders) => {
|
||||
const headersAmount = Number($assetHeaders.length);
|
||||
|
||||
cy.wrap($assetHeaders).each(($header) => {
|
||||
expect($header).to.not.be.empty;
|
||||
});
|
||||
|
||||
cy.get('.language-json')
|
||||
.each(($asset) => {
|
||||
expect($asset).to.not.be.empty;
|
||||
})
|
||||
.then(($list) => {
|
||||
expect($list).to.have.length(headersAmount);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class BlocksPage extends BasePage {
|
||||
blockRow = 'block-row';
|
||||
transactionsRow = 'transaction-row';
|
||||
blockHeight = 'block-height';
|
||||
numberOfTransactions = 'num-txs';
|
||||
validatorLink = 'validator-link';
|
||||
blockTime = 'block-time';
|
||||
refreshBtn = 'refresh';
|
||||
blockHeader = 'block-header';
|
||||
minedByValidator = 'block-validator';
|
||||
previousBlockBtn = 'previous-block';
|
||||
nextBlockBtn = 'next-block';
|
||||
jumpToBlockInput = 'block-input';
|
||||
jumpToBlockSubmit = 'go-submit';
|
||||
infiniteScrollWrapper = 'infinite-scroll-wrapper';
|
||||
|
||||
private waitForBlocksResponse() {
|
||||
cy.contains('Loading...').should('not.exist', { timeout: 18000 });
|
||||
}
|
||||
|
||||
validateBlocksPageDisplayed() {
|
||||
this.waitForBlocksResponse();
|
||||
cy.getByTestId(this.blockRow).should('have.length.above', 1);
|
||||
cy.getByTestId(this.blockHeight).first().should('not.be.empty');
|
||||
cy.getByTestId(this.numberOfTransactions).first().should('not.be.empty');
|
||||
cy.getByTestId(this.validatorLink).first().should('not.be.empty');
|
||||
cy.getByTestId(this.blockTime).first().should('not.be.empty');
|
||||
}
|
||||
|
||||
clickOnTopBlockHeight() {
|
||||
this.waitForBlocksResponse();
|
||||
cy.getByTestId(this.blockHeight).first().click();
|
||||
}
|
||||
|
||||
validateBlockValidatorPage() {
|
||||
cy.getByTestId(this.minedByValidator).should('not.be.empty');
|
||||
cy.getByTestId(this.blockTime).should('not.be.empty');
|
||||
cy.get('body').then(($body) => {
|
||||
if ($body.find(`[data-testid=${this.transactionsRow}] > td`).length) {
|
||||
cy.get(`[data-testid=${this.transactionsRow}] > td`).each(($cell) => {
|
||||
cy.wrap($cell).should('not.be.empty');
|
||||
});
|
||||
} else {
|
||||
cy.slack('Unable to find any transactions on page');
|
||||
cy.screenshot();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
navigateToPreviousBlock() {
|
||||
cy.getByTestId(this.blockHeader)
|
||||
.invoke('text')
|
||||
.then(($blockHeaderTxt) => {
|
||||
const blockHeight = parseInt($blockHeaderTxt.replace('BLOCK ', ''));
|
||||
this.clickPreviousBlock();
|
||||
cy.getByTestId(this.blockHeader)
|
||||
.invoke('text')
|
||||
.then(($newBlockHeaderTxt) => {
|
||||
const newBlockHeight = parseInt(
|
||||
$newBlockHeaderTxt.replace('BLOCK ', '')
|
||||
);
|
||||
expect(newBlockHeight).to.be.lessThan(blockHeight);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
navigateToNextBlock() {
|
||||
cy.getByTestId(this.blockHeader)
|
||||
.invoke('text')
|
||||
.then(($blockHeaderTxt) => {
|
||||
const blockHeight = parseInt($blockHeaderTxt.replace('BLOCK ', ''));
|
||||
this.clickNextBlock();
|
||||
cy.getByTestId(this.blockHeader)
|
||||
.invoke('text')
|
||||
.then(($newBlockHeaderTxt) => {
|
||||
const newBlockHeight = parseInt(
|
||||
$newBlockHeaderTxt.replace('BLOCK ', '')
|
||||
);
|
||||
expect(newBlockHeight).to.be.greaterThan(blockHeight);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
navigateToLastBlockOnPage() {
|
||||
this.waitForBlocksResponse();
|
||||
cy.getByTestId(this.infiniteScrollWrapper).children().scrollTo('bottom');
|
||||
}
|
||||
|
||||
navigateToOlderBlocksWithInfiniteScroll(
|
||||
expectedBlocks: number,
|
||||
scrollAttempts: number
|
||||
) {
|
||||
cy.intercept('*blockchain?maxHeight*').as('blockchain_load');
|
||||
|
||||
cy.getByTestId(this.blockHeight)
|
||||
.last()
|
||||
.invoke('text')
|
||||
.then(($initialLastBlockHeight) => {
|
||||
for (let index = 0; index < scrollAttempts; index++) {
|
||||
cy.getByTestId(this.infiniteScrollWrapper)
|
||||
.children()
|
||||
.children()
|
||||
.invoke('css', 'height')
|
||||
.then((scrollTarget) => {
|
||||
cy.getByTestId(this.infiniteScrollWrapper)
|
||||
.children()
|
||||
.scrollTo(0, scrollTarget.toString(), { easing: 'linear' })
|
||||
.wait('@blockchain_load');
|
||||
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(50); // Need this as although network response has arrived it takes a few millisecs for the css height to expand
|
||||
});
|
||||
}
|
||||
|
||||
cy.getByTestId(this.blockHeight)
|
||||
.last()
|
||||
.invoke('text')
|
||||
.then(($lastBlockHeight) => {
|
||||
const totalBlocksLoadedSinceScrollBegan =
|
||||
parseInt($initialLastBlockHeight) - parseInt($lastBlockHeight);
|
||||
expect(totalBlocksLoadedSinceScrollBegan).to.be.at.least(
|
||||
expectedBlocks
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
clickPreviousBlock() {
|
||||
cy.getByTestId(this.previousBlockBtn).click();
|
||||
}
|
||||
|
||||
clickNextBlock() {
|
||||
cy.getByTestId(this.nextBlockBtn).click();
|
||||
}
|
||||
|
||||
jumpToBlock(blockNumber: string) {
|
||||
cy.getByTestId(this.jumpToBlockInput).type(blockNumber);
|
||||
cy.getByTestId(this.jumpToBlockSubmit).click();
|
||||
}
|
||||
|
||||
verifyPreviousBtnDisabled() {
|
||||
cy.getByTestId(this.previousBlockBtn).find('button').should('be.disabled');
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class GenesisPage extends BasePage {
|
||||
genesisHeader = 'genesis-header';
|
||||
|
||||
genesisFieldsDisplayed() {
|
||||
this.validateBlockDataDisplayed(this.genesisHeader);
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
import BasePage from './base-page';
|
||||
export default class HomePage extends BasePage {
|
||||
statsEnvironmentTitle = 'stats-environment';
|
||||
statsTitle = 'stats-title';
|
||||
statsValue = 'stats-value';
|
||||
|
||||
verifyStatsEnvironment() {
|
||||
const deployedEnv = Cypress.env('environment').toUpperCase();
|
||||
cy.getByTestId(this.statsEnvironmentTitle).should(
|
||||
'have.text',
|
||||
`/ ${deployedEnv}`
|
||||
);
|
||||
}
|
||||
|
||||
verifyStatsTitlesDisplayed() {
|
||||
const statTitles = [
|
||||
'Status',
|
||||
'Height',
|
||||
'Validating nodes',
|
||||
'Uptime',
|
||||
'Total nodes',
|
||||
'Inactive nodes',
|
||||
'Total staked',
|
||||
'Backlog',
|
||||
'Trades / second',
|
||||
'Orders / block',
|
||||
'Orders / second',
|
||||
'Transactions / block',
|
||||
'Block time',
|
||||
'Time',
|
||||
'App',
|
||||
'Tendermint',
|
||||
'Up since',
|
||||
'Chain ID',
|
||||
];
|
||||
|
||||
cy.getByTestId(this.statsTitle).then(($list) => {
|
||||
cy.wrap($list).should('have.length', 18);
|
||||
});
|
||||
|
||||
cy.getByTestId(this.statsTitle)
|
||||
.each(($title, index) => {
|
||||
cy.wrap($title).should('have.text', statTitles[index]);
|
||||
})
|
||||
.then(($list) => {
|
||||
cy.wrap($list).should('have.length', 18);
|
||||
});
|
||||
}
|
||||
|
||||
verifyStatsValuesDisplayed() {
|
||||
cy.getByTestId(this.statsValue).eq(0).should('have.text', 'CONNECTED');
|
||||
cy.getByTestId(this.statsValue).eq(1).should('not.be.empty');
|
||||
cy.getByTestId(this.statsValue).eq(2).should('have.text', '2');
|
||||
cy.getByTestId(this.statsValue)
|
||||
.eq(3)
|
||||
.invoke('text')
|
||||
.should('match', /\d+d \d+h \d+m \d+s/i);
|
||||
cy.getByTestId(this.statsValue).eq(4).should('have.text', '2');
|
||||
cy.getByTestId(this.statsValue).eq(5).should('have.text', '0');
|
||||
cy.getByTestId(this.statsValue).eq(6).should('not.be.empty');
|
||||
cy.getByTestId(this.statsValue).eq(7).should('have.text', '0');
|
||||
cy.getByTestId(this.statsValue).eq(8).should('have.text', '0');
|
||||
cy.getByTestId(this.statsValue).eq(9).should('have.text', '0');
|
||||
cy.getByTestId(this.statsValue).eq(10).should('have.text', '0');
|
||||
cy.getByTestId(this.statsValue).eq(11).should('not.be.empty');
|
||||
cy.getByTestId(this.statsValue).eq(12).should('not.be.empty');
|
||||
cy.getByTestId(this.statsValue).eq(13).should('not.be.empty');
|
||||
if (Cypress.env('NIGHTLY_RUN') != true) {
|
||||
cy.getByTestId(this.statsValue)
|
||||
.eq(14)
|
||||
.invoke('text')
|
||||
.should('match', /v\d+\.\d+\.\d+/i);
|
||||
}
|
||||
cy.getByTestId(this.statsValue)
|
||||
.eq(15)
|
||||
.invoke('text')
|
||||
.should('match', /\d+\.\d+\.\d+/i);
|
||||
cy.getByTestId(this.statsValue).eq(16).should('not.be.empty');
|
||||
cy.getByTestId(this.statsValue).eq(17).should('not.be.empty');
|
||||
}
|
||||
|
||||
verifyStatsBlockHeightUpdating() {
|
||||
cy.getByTestId(this.statsValue)
|
||||
.eq(1)
|
||||
.invoke('text')
|
||||
.then((blockHeightTxt) => {
|
||||
cy.getByTestId(this.statsValue)
|
||||
.eq(1)
|
||||
.invoke('text')
|
||||
.should((newBlockHeightTxt) => {
|
||||
expect(blockHeightTxt).not.to.eq(newBlockHeightTxt);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class MarketsPage extends BasePage {
|
||||
marketHeaders = 'markets-header';
|
||||
|
||||
validateMarketDataDisplayed() {
|
||||
this.validateBlockDataDisplayed(this.marketHeaders);
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class NetworkParametersPage extends BasePage {
|
||||
networkParametersHeader = 'network-param-header';
|
||||
parameters = 'parameters';
|
||||
jsonParamNameClassName = '.hljs-attr';
|
||||
jsonParamValueStringClassName = '.hljs-string';
|
||||
jsonParamValueNumberClassName = '.hljs-number';
|
||||
parameterKeyValueRow = 'key-value-table-row';
|
||||
|
||||
verifyNetworkParametersDisplayed() {
|
||||
cy.getByTestId(this.networkParametersHeader).should(
|
||||
'have.text',
|
||||
'Network Parameters'
|
||||
);
|
||||
|
||||
cy.get(this.jsonParamNameClassName)
|
||||
.should('have.length.at.least', 18)
|
||||
.each(($paramName) => {
|
||||
cy.wrap($paramName).should('not.be.empty');
|
||||
});
|
||||
cy.get(this.jsonParamValueStringClassName)
|
||||
.should('have.length.at.least', 6)
|
||||
.each(($paramValue) => {
|
||||
cy.wrap($paramValue).should('not.be.empty');
|
||||
});
|
||||
|
||||
cy.get(this.jsonParamValueNumberClassName)
|
||||
.should('have.length.at.least', 7)
|
||||
.each(($paramValue) => {
|
||||
cy.wrap($paramValue).should('not.be.empty');
|
||||
});
|
||||
|
||||
cy.getByTestId(this.parameterKeyValueRow).each(($row) => {
|
||||
cy.wrap($row).find('dt').should('not.be.empty');
|
||||
cy.wrap($row).find('dd').should('not.be.empty');
|
||||
});
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class TransactionsPage extends BasePage {
|
||||
transactionsList = 'transactions-list';
|
||||
transactionRow = 'transaction-row';
|
||||
blockHeight = 'block-height';
|
||||
numberOfTransactions = 'num-txs';
|
||||
validatorLink = 'validator-link';
|
||||
blockTime = 'block-time';
|
||||
refreshBtn = 'refresh';
|
||||
txHash = 'hash';
|
||||
txSubmittedBy = 'submitted-by';
|
||||
txBlock = 'block';
|
||||
txEncodedTnx = 'encoded-tnx';
|
||||
txType = 'tx-type';
|
||||
|
||||
validateTransactionsPagedisplayed() {
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(5000); // Wait for transactions to load if there are any
|
||||
cy.getByTestId(this.transactionRow).should('have.length.above', 1);
|
||||
}
|
||||
|
||||
validateRefreshBtn() {
|
||||
cy.intercept('GET', '**/blockchain').as('get-blockchain');
|
||||
cy.getByTestId(this.refreshBtn).click();
|
||||
cy.wait('@get-blockchain').its('response.statusCode').should('eq', 200);
|
||||
}
|
||||
|
||||
validateTxDetailsAreDisplayed() {
|
||||
// TODO fail test when there are no txs once running with Capsule
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(1000); // Wait for transactions to load if there are any
|
||||
cy.get('body').then(($body) => {
|
||||
if ($body.find(`[data-testid=${this.txHash}]`).length) {
|
||||
cy.getByTestId(this.txHash).invoke('text').should('have.length', 64);
|
||||
cy.getByTestId(this.txSubmittedBy)
|
||||
.find('a')
|
||||
.then(($address) => {
|
||||
cy.wrap($address).should('have.attr', 'href');
|
||||
cy.wrap($address).invoke('text').should('have.length', 66);
|
||||
});
|
||||
cy.getByTestId(this.txBlock).should('not.be.empty');
|
||||
cy.getByTestId(this.txEncodedTnx).should('not.be.empty');
|
||||
cy.getByTestId(this.txType)
|
||||
.should('not.be.empty')
|
||||
.invoke('text')
|
||||
.then((txTypeTxt) => {
|
||||
if (txTypeTxt == 'Order Submission') {
|
||||
cy.get('.hljs-attr')
|
||||
.should('have.length.at.least', 8)
|
||||
.each(($propertyName) => {
|
||||
cy.wrap($propertyName).should('not.be.empty');
|
||||
});
|
||||
cy.get('.hljs-string')
|
||||
.should('have.length.at.least', 8)
|
||||
.each(($propertyValue) => {
|
||||
cy.wrap($propertyValue).should('not.be.empty');
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cy.slack('Unable to find any transactions on page');
|
||||
cy.screenshot();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
clickOnTopTransaction() {
|
||||
// TODO fail test when there are no txs once running with Capsule
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(1000); // Wait for transactions to load if there are any
|
||||
cy.get('body').then(($body) => {
|
||||
if ($body.find(`[data-testid=${this.transactionRow}]`).length) {
|
||||
cy.getByTestId(this.transactionRow)
|
||||
.first()
|
||||
.find('a')
|
||||
.first()
|
||||
.click({ force: true });
|
||||
} else {
|
||||
cy.slack('Unable to find any transactions on page');
|
||||
cy.screenshot();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
import BasePage from './base-page';
|
||||
|
||||
export default class ValidatorPage extends BasePage {
|
||||
tendermintHeader = 'tendermint-header';
|
||||
vegaHeader = 'vega-header';
|
||||
tendermintData = 'tendermint-data';
|
||||
vegaData = 'vega-data';
|
||||
|
||||
validateValidatorsDisplayed() {
|
||||
cy.getByTestId(this.tendermintHeader).should(
|
||||
'have.text',
|
||||
'Tendermint data'
|
||||
);
|
||||
cy.getByTestId(this.tendermintData).should('not.be.empty');
|
||||
cy.getByTestId(this.vegaHeader).should('have.text', 'Vega data');
|
||||
cy.getByTestId(this.vegaData).should('not.be.empty');
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
import { Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
|
||||
import AssetsPage from '../pages/assets-page';
|
||||
const assetPage = new AssetsPage();
|
||||
|
||||
When('I navigate to the asset page', () => {
|
||||
assetPage.navigateToAssets();
|
||||
});
|
||||
|
||||
Then('asset page is correctly displayed', () => {
|
||||
assetPage.validateAssetsDisplayed();
|
||||
});
|
@ -1,50 +0,0 @@
|
||||
import { Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
|
||||
import BlocksPage from '../pages/blocks-page';
|
||||
const blocksPage = new BlocksPage();
|
||||
|
||||
When('I navigate to the blocks page', () => {
|
||||
blocksPage.navigateToBlocks();
|
||||
});
|
||||
|
||||
When('I click on top block', () => {
|
||||
blocksPage.clickOnTopBlockHeight();
|
||||
});
|
||||
|
||||
When('jump to first block', () => {
|
||||
blocksPage.jumpToBlock('1');
|
||||
});
|
||||
|
||||
Then('blocks page is correctly displayed', () => {
|
||||
blocksPage.validateBlocksPageDisplayed();
|
||||
});
|
||||
|
||||
Then('validator block page is correctly displayed', () => {
|
||||
blocksPage.validateBlockValidatorPage();
|
||||
});
|
||||
|
||||
Then('I am on the previous block when I click previous', () => {
|
||||
blocksPage.navigateToPreviousBlock();
|
||||
});
|
||||
|
||||
Then('previous button is disabled', () => {
|
||||
blocksPage.verifyPreviousBtnDisabled();
|
||||
});
|
||||
|
||||
Then('I am on the second block when I click next', () => {
|
||||
blocksPage.navigateToNextBlock();
|
||||
});
|
||||
|
||||
Then('I scroll down to the last block on the page', () => {
|
||||
blocksPage.navigateToLastBlockOnPage();
|
||||
});
|
||||
|
||||
Then(
|
||||
'I can expect to see at least {int} blocks if i scroll {int} times',
|
||||
(expectedBlocks, scrollAttempts) => {
|
||||
blocksPage.navigateToOlderBlocksWithInfiniteScroll(
|
||||
expectedBlocks,
|
||||
scrollAttempts
|
||||
);
|
||||
}
|
||||
);
|
@ -1,26 +0,0 @@
|
||||
import { Given, Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
import BasePage from '../pages/base-page';
|
||||
const basePage = new BasePage();
|
||||
|
||||
Given('I am on mobile and open the toggle menu', () => {
|
||||
cy.viewport('iphone-x');
|
||||
cy.visit('/');
|
||||
basePage.clickOnToggle();
|
||||
});
|
||||
|
||||
Given('I am on the homepage', () => {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
When('I search for {string}', (searchText) => {
|
||||
basePage.search(searchText);
|
||||
basePage.clickSearch();
|
||||
});
|
||||
|
||||
Then('I am redirected to page containing id {string}', (expectedUrl) => {
|
||||
basePage.validateUrl(expectedUrl);
|
||||
});
|
||||
|
||||
Then('search error message {string} is displayed', (expectedErrorMsg) => {
|
||||
basePage.validateSearchErrorDisplayed(expectedErrorMsg);
|
||||
});
|
@ -1,11 +0,0 @@
|
||||
import { Then } from 'cypress-cucumber-preprocessor/steps';
|
||||
|
||||
import HomePage from '../pages/home-page';
|
||||
const homePage = new HomePage();
|
||||
|
||||
Then('the stats for deployed environment are correctly displayed', () => {
|
||||
homePage.verifyStatsEnvironment();
|
||||
homePage.verifyStatsTitlesDisplayed();
|
||||
homePage.verifyStatsValuesDisplayed();
|
||||
homePage.verifyStatsBlockHeightUpdating();
|
||||
});
|
@ -1,12 +0,0 @@
|
||||
import { Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
|
||||
import MarketsPage from '../pages/markets-page';
|
||||
const marketsPage = new MarketsPage();
|
||||
|
||||
When('I navigate to the markets page', () => {
|
||||
marketsPage.navigateToMarkets();
|
||||
});
|
||||
|
||||
Then('markets page is correctly displayed', () => {
|
||||
marketsPage.validateMarketDataDisplayed();
|
||||
});
|
@ -1,11 +0,0 @@
|
||||
import { Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
import NetworkPage from '../pages/network-page';
|
||||
const networkPage = new NetworkPage();
|
||||
|
||||
When('I navigate to network parameters page', () => {
|
||||
networkPage.navigateToNetworkParameters();
|
||||
});
|
||||
|
||||
Then('network parameters page is correctly displayed', () => {
|
||||
networkPage.verifyNetworkParametersDisplayed();
|
||||
});
|
@ -1,30 +0,0 @@
|
||||
import { Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
|
||||
import TransactionsPage from '../pages/transactions-page';
|
||||
const transactionsPage = new TransactionsPage();
|
||||
|
||||
When('I navigate to the transactions page', () => {
|
||||
transactionsPage.navigateToTxs();
|
||||
});
|
||||
|
||||
When('I navigate to the blocks page', () => {
|
||||
transactionsPage.navigateToBlocks();
|
||||
});
|
||||
|
||||
When('I click on the top transaction', () => {
|
||||
transactionsPage.clickOnTopTransaction();
|
||||
});
|
||||
|
||||
Then('transactions page is correctly displayed', () => {
|
||||
transactionsPage.validateTransactionsPagedisplayed();
|
||||
transactionsPage.validateRefreshBtn();
|
||||
});
|
||||
|
||||
Then('blocks page is correctly displayed', () => {
|
||||
transactionsPage.validateTransactionsPagedisplayed();
|
||||
transactionsPage.validateRefreshBtn();
|
||||
});
|
||||
|
||||
Then('transaction details are displayed', () => {
|
||||
transactionsPage.validateTxDetailsAreDisplayed();
|
||||
});
|
@ -1,12 +0,0 @@
|
||||
import { Then, When } from 'cypress-cucumber-preprocessor/steps';
|
||||
|
||||
import ValidatorPage from '../pages/validators-page';
|
||||
const validatorsPage = new ValidatorPage();
|
||||
|
||||
When('I navigate to the validators page', () => {
|
||||
validatorsPage.navigateToValidators();
|
||||
});
|
||||
|
||||
Then('validators page is correctly displayed', () => {
|
||||
validatorsPage.validateValidatorsDisplayed();
|
||||
});
|
@ -0,0 +1,87 @@
|
||||
describe('market selector', () => {
|
||||
let markets;
|
||||
before(() => {
|
||||
cy.intercept('POST', '/query', (req) => {
|
||||
const { body } = req;
|
||||
if (body.operationName === 'SimpleMarkets') {
|
||||
req.alias = `gqlSimpleMarketsQuery`;
|
||||
}
|
||||
});
|
||||
cy.visit('/markets');
|
||||
cy.wait('@gqlSimpleMarketsQuery').then((response) => {
|
||||
if (response.response?.body?.data?.markets?.length) {
|
||||
markets = response.response?.body?.data?.markets;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should be properly rendered', () => {
|
||||
if (markets) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
cy.get('input[placeholder="Search"]').should(
|
||||
'have.value',
|
||||
markets[0].name
|
||||
);
|
||||
cy.getByTestId('arrow-button').click();
|
||||
cy.getByTestId('market-pane').should('be.visible');
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.should('contain.text', markets[0].name);
|
||||
cy.getByTestId('market-pane').children().find('[role="button"]').click();
|
||||
cy.getByTestId('market-pane').should('not.be.visible');
|
||||
}
|
||||
});
|
||||
|
||||
it('typing should change list', () => {
|
||||
if (markets) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
cy.get('input[placeholder="Search"]').type('{backspace}');
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.should('have.length', 1);
|
||||
cy.get('input[placeholder="Search"]').clear();
|
||||
cy.get('input[placeholder="Search"]').type('a');
|
||||
const filtered = markets.filter((market) => market.name.match(/a/i));
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.should('have.length', filtered.length);
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.last()
|
||||
.click();
|
||||
cy.location('pathname').should(
|
||||
'eq',
|
||||
`/trading/${filtered[filtered.length - 1].id}`
|
||||
);
|
||||
cy.get('input[placeholder="Search"]').should(
|
||||
'have.value',
|
||||
filtered[filtered.length - 1].name
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('mobile view', () => {
|
||||
if (markets) {
|
||||
cy.viewport('iphone-xr');
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
cy.get('[role="dialog"]').should('not.exist');
|
||||
cy.getByTestId('arrow-button').click();
|
||||
cy.get('[role="dialog"]').should('be.visible');
|
||||
cy.get('input[placeholder="Search"]').clear();
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.should('have.length', markets.length);
|
||||
cy.pause();
|
||||
cy.getByTestId('dialog-close').click();
|
||||
cy.get('input[placeholder="Search"]').should(
|
||||
'have.value',
|
||||
markets[0].name
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
@ -2,30 +2,45 @@ import * as React from 'react';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import Box from '@mui/material/Box';
|
||||
import { Stepper } from '../stepper';
|
||||
import type { DealTicketQuery_market, Order } from '@vegaprotocol/deal-ticket';
|
||||
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
|
||||
import { Button, InputError } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
ExpirySelector,
|
||||
SideSelector,
|
||||
TimeInForceSelector,
|
||||
TypeSelector,
|
||||
getDefaultOrder,
|
||||
useOrderValidation,
|
||||
useOrderSubmit,
|
||||
DealTicketAmount,
|
||||
MarketSelector,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import {
|
||||
OrderTimeInForce,
|
||||
OrderType,
|
||||
VegaWalletOrderTimeInForce as OrderTimeInForce,
|
||||
VegaWalletOrderType as OrderType,
|
||||
VegaTxStatus,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { t, addDecimal, toDecimal } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
getDefaultOrder,
|
||||
useOrderValidation,
|
||||
useOrderSubmit,
|
||||
} from '@vegaprotocol/orders';
|
||||
import { useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import MarketNameRenderer from '../simple-market-list/simple-market-renderer';
|
||||
|
||||
interface DealTicketMarketProps {
|
||||
market: DealTicketQuery_market;
|
||||
}
|
||||
|
||||
export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
|
||||
const navigate = useNavigate();
|
||||
const setMarket = useCallback(
|
||||
(marketId) => {
|
||||
navigate(`/trading/${marketId}`);
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
|
||||
const {
|
||||
register,
|
||||
control,
|
||||
@ -70,7 +85,13 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
|
||||
{
|
||||
label: 'Select Asset',
|
||||
description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
|
||||
component: <h1 className="font-bold mb-16">{market.name}</h1>,
|
||||
component: (
|
||||
<MarketSelector
|
||||
market={market}
|
||||
setMarket={setMarket}
|
||||
ItemRenderer={MarketNameRenderer}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'Select Order Type',
|
||||
|
@ -1,23 +1,23 @@
|
||||
import React from 'react';
|
||||
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
|
||||
import type { MarketNames_markets } from '@vegaprotocol/deal-ticket';
|
||||
import SimpleMarketExpires from './simple-market-expires';
|
||||
|
||||
interface Props {
|
||||
data: SimpleMarkets_markets;
|
||||
market: MarketNames_markets;
|
||||
}
|
||||
|
||||
const MarketNameRenderer = ({ data }: Props) => {
|
||||
const MarketNameRenderer = ({ market }: Props) => {
|
||||
return (
|
||||
<div className="flex h-full items-center grid grid-rows-2 grid-flow-col gap-x-8 gap-y-0 grid-cols-[min-content,1fr,1fr]">
|
||||
<div className="w-60 row-span-2 bg-pink rounded-full w-44 h-44 bg-gradient-to-br from-white-60 to--white-80 opacity-30" />
|
||||
<div className="col-span-2 uppercase justify-start text-black dark:text-white text-market self-end">
|
||||
{data.name}{' '}
|
||||
{market.name}{' '}
|
||||
<SimpleMarketExpires
|
||||
tags={data.tradableInstrument.instrument.metadata.tags}
|
||||
tags={market.tradableInstrument.instrument.metadata.tags}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2 ui-small text-deemphasise dark:text-midGrey self-start leading-3">
|
||||
{data.tradableInstrument.instrument.product.quoteName}
|
||||
<div className="col-span-2 text-ui-small text-deemphasise dark:text-midGrey self-start leading-3">
|
||||
{market.tradableInstrument.instrument.product.quoteName}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -21,7 +21,7 @@ const useColumnDefinitions = ({ onClick }: Props) => {
|
||||
minWidth: 300,
|
||||
field: 'name',
|
||||
cellRenderer: ({ data }: { data: SimpleMarketsType }) => (
|
||||
<MarketNameRenderer data={data} />
|
||||
<MarketNameRenderer market={data} />
|
||||
),
|
||||
},
|
||||
{
|
||||
|
@ -2,6 +2,7 @@ const { join } = require('path');
|
||||
const { createGlobPatternsForDependencies } = require('@nrwl/next/tailwind');
|
||||
const theme = require('../../libs/tailwindcss-config/src/theme-lite');
|
||||
const vegaCustomClasses = require('../../libs/tailwindcss-config/src/vega-custom-classes');
|
||||
const vegaCustomClassesLite = require('../../libs/tailwindcss-config/src/vega-custom-classes-lite');
|
||||
|
||||
module.exports = {
|
||||
content: [
|
||||
@ -11,5 +12,5 @@ module.exports = {
|
||||
],
|
||||
darkMode: 'class',
|
||||
theme,
|
||||
plugins: [vegaCustomClasses],
|
||||
plugins: [vegaCustomClasses, vegaCustomClassesLite],
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -38,7 +38,7 @@
|
||||
"tranche_end": "2022-11-26T13:48:10.000Z",
|
||||
"total_added": "100",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "38.375643708777274",
|
||||
"locked_amount": "37.074508498224257",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "100",
|
||||
@ -242,7 +242,7 @@
|
||||
"tranche_end": "2022-10-12T00:53:20.000Z",
|
||||
"total_added": "1100",
|
||||
"total_removed": "673.04388635",
|
||||
"locked_amount": "284.894035388127847",
|
||||
"locked_amount": "270.58154807204466",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1000",
|
||||
|
@ -69,7 +69,7 @@
|
||||
"tranche_end": "2022-10-12T00:53:20.000Z",
|
||||
"total_added": "1010.000000000000000001",
|
||||
"total_removed": "668.4622323651",
|
||||
"locked_amount": "261.58452340182647770025899457762557077",
|
||||
"locked_amount": "248.4430577752410060002459832255200406",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1000",
|
||||
|
@ -18,6 +18,7 @@ module.exports = defineConfig({
|
||||
env: {
|
||||
ethProviderUrl: 'http://localhost:8545/',
|
||||
ethWalletPublicKey: '0xEe7D375bcB50C26d52E1A4a472D8822A2A22d94F',
|
||||
ethWalletPublicKeyTruncated: '0xEe7D…d94F',
|
||||
ethStakingBridgeContractAddress:
|
||||
'0x9135f5afd6F055e731bca2348429482eE614CFfA',
|
||||
vegaWalletName: 'capsule_wallet',
|
||||
|
@ -1,31 +1,28 @@
|
||||
/// <reference types="cypress" />
|
||||
import navigation from '../../locators/navigation.locators';
|
||||
import staking from '../../locators/staking.locators';
|
||||
import wallet from '../../locators/wallet.locators';
|
||||
import '../../support/staking.functions';
|
||||
import '../../support/vega-wallet.functions';
|
||||
import '../../support/eth-wallet.functions';
|
||||
import '../../support/wallet-teardown.functions';
|
||||
const pageSpinner = 'splash-loader';
|
||||
const menuBar = 'nav';
|
||||
const validatorList = '[data-testid="node-list-item-name"]';
|
||||
const removeStakeRadioButton = '[data-testid="remove-stake-radio"]';
|
||||
const tokenAmountInputBox = '[data-testid="token-amount-input"]';
|
||||
const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
|
||||
const stakeNextEpochValue = '[data-testid="stake-next-epoch"]';
|
||||
const vegaWalletContainer = '[data-testid="vega-wallet"]';
|
||||
|
||||
const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort');
|
||||
|
||||
context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
context('Staking Flow - with eth and vega wallets connected', function () {
|
||||
before('visit staking tab and connect vega wallet', function () {
|
||||
cy.vega_wallet_import();
|
||||
cy.visit('/');
|
||||
cy.get(navigation.section, { timeout: 20000 }).should('be.visible');
|
||||
cy.get(menuBar, { timeout: 20000 }).should('be.visible');
|
||||
cy.vega_wallet_connect();
|
||||
cy.vega_wallet_set_specified_approval_amount('1000');
|
||||
cy.reload();
|
||||
cy.get(navigation.section, { timeout: 20000 }).should('be.visible');
|
||||
cy.get(menuBar, { timeout: 20000 }).should('be.visible');
|
||||
cy.ethereum_wallet_connect();
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.get(navigation.spinner, { timeout: 20000 }).should('not.exist');
|
||||
cy.get(staking.validatorNames).first().invoke('text').as('validatorName');
|
||||
cy.get(staking.validatorNames)
|
||||
.last()
|
||||
.invoke('text')
|
||||
.as('otherValidatorName');
|
||||
cy.navigate_to('staking');
|
||||
cy.get(pageSpinner, { timeout: 20000 }).should('not.exist');
|
||||
cy.get(validatorList).first().invoke('text').as('validatorName');
|
||||
cy.get(validatorList).last().invoke('text').as('otherValidatorName');
|
||||
});
|
||||
|
||||
describe('Eth wallet - contains VEGA tokens', function () {
|
||||
@ -33,7 +30,7 @@ context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
'teardown wallet & drill into a specific validator',
|
||||
function () {
|
||||
cy.vega_wallet_teardown();
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.navigate_to('staking');
|
||||
}
|
||||
);
|
||||
|
||||
@ -47,37 +44,37 @@ context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
);
|
||||
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_add_stake('2');
|
||||
cy.vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_unstaked_value_is('1.000000000000000000');
|
||||
cy.vega_wallet_check_validator_staked_value_is(
|
||||
vega_wallet_check_validator_staked_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
cy.staking_validator_page_check_stake_this_epoch_value('2.0');
|
||||
staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
staking_validator_page_check_stake_this_epoch_value('2.0');
|
||||
});
|
||||
|
||||
it('Able to stake against mulitple validators', function () {
|
||||
cy.staking_page_associate_tokens('5');
|
||||
cy.vega_wallet_check_unstaked_value_is('5.000000000000000000');
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_add_stake('2');
|
||||
cy.vega_wallet_check_validator_staked_value_is(
|
||||
vega_wallet_check_validator_staked_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.get(staking.validatorNames).contains(this.otherValidatorName).click();
|
||||
cy.navigate_to('staking');
|
||||
cy.get(validatorList).contains(this.otherValidatorName).click();
|
||||
cy.staking_validator_page_add_stake('1');
|
||||
cy.vega_wallet_check_validator_staked_value_is(
|
||||
vega_wallet_check_validator_staked_value_is(
|
||||
this.otherValidatorName,
|
||||
'1.000000000000000000'
|
||||
);
|
||||
@ -89,37 +86,37 @@ context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
cy.vega_wallet_check_unstaked_value_is('4.000000000000000000');
|
||||
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_add_stake('3');
|
||||
cy.staking_validator_page_check_stake_next_epoch_value('3.0');
|
||||
cy.vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
staking_validator_page_check_stake_next_epoch_value('3.0');
|
||||
vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
this.validatorName,
|
||||
'3.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_unstaked_value_is('1.000000000000000000');
|
||||
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.navigate_to('staking');
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_removeStake('1');
|
||||
cy.staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
cy.staking_validator_page_check_stake_this_epoch_value('3.0');
|
||||
cy.vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
staking_validator_page_check_stake_this_epoch_value('3.0');
|
||||
vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_validator_stake_this_epoch_value_is(
|
||||
vega_wallet_check_validator_stake_this_epoch_value_is(
|
||||
this.validatorName,
|
||||
'3.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_unstaked_value_is('2.000000000000000000');
|
||||
cy.vega_wallet_check_validator_staked_value_is(
|
||||
vega_wallet_check_validator_staked_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
cy.staking_validator_page_check_stake_this_epoch_value('2.0');
|
||||
staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
staking_validator_page_check_stake_this_epoch_value('2.0');
|
||||
});
|
||||
|
||||
it('Able to remove a full stake against a validator', function () {
|
||||
@ -127,33 +124,33 @@ context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
cy.vega_wallet_check_unstaked_value_is('3.000000000000000000');
|
||||
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_add_stake('1');
|
||||
cy.vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
this.validatorName,
|
||||
'1.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_unstaked_value_is('2.000000000000000000');
|
||||
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.navigate_to('staking');
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_removeStake('1');
|
||||
cy.staking_validator_page_check_stake_next_epoch_value('0.0');
|
||||
staking_validator_page_check_stake_next_epoch_value('0.0');
|
||||
|
||||
cy.vega_wallet_check_validator_stake_this_epoch_value_is(
|
||||
vega_wallet_check_validator_stake_this_epoch_value_is(
|
||||
this.validatorName,
|
||||
'1.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
this.validatorName,
|
||||
'0.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_unstaked_value_is('3.000000000000000000');
|
||||
cy.staking_validator_page_check_stake_next_epoch_value('0.0');
|
||||
cy.staking_validator_page_check_stake_this_epoch_value('0.0');
|
||||
cy.vega_wallet_check_validator_no_longer_showing(this.validatorName);
|
||||
staking_validator_page_check_stake_next_epoch_value('0.0');
|
||||
staking_validator_page_check_stake_this_epoch_value('0.0');
|
||||
vega_wallet_check_validator_no_longer_showing(this.validatorName);
|
||||
});
|
||||
|
||||
it.skip('Unable to remove a stake with a negative value for a validator', function () {
|
||||
@ -161,22 +158,22 @@ context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
cy.vega_wallet_check_unstaked_value_is('3.000000000000000000');
|
||||
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_add_stake('2');
|
||||
cy.staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
cy.vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_unstaked_value_is('1.000000000000000000');
|
||||
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(staking.removeStakeRadioButton).click({ force: true });
|
||||
cy.get(staking.tokenAmountInput).type('-0.1');
|
||||
cy.navigate_to('staking');
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
cy.get(removeStakeRadioButton).click({ force: true });
|
||||
cy.get(tokenAmountInputBox).type('-0.1');
|
||||
cy.contains('Waiting for next epoch to start', { timeout: 10000 });
|
||||
cy.get(staking.tokenInputSubmit)
|
||||
cy.get(tokenSubmitButton)
|
||||
.should('be.disabled', { timeout: 8000 })
|
||||
.and('contain', `Remove -0.1 $VEGA tokens at the end of epoch`)
|
||||
.and('be.visible');
|
||||
@ -187,22 +184,22 @@ context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
cy.vega_wallet_check_unstaked_value_is('3.000000000000000000');
|
||||
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_add_stake('2');
|
||||
cy.staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
cy.vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
staking_validator_page_check_stake_next_epoch_value('2.0');
|
||||
vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_unstaked_value_is('1.000000000000000000');
|
||||
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(staking.removeStakeRadioButton).click({ force: true });
|
||||
cy.get(staking.tokenAmountInput).type(4);
|
||||
cy.navigate_to('staking');
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
cy.get(removeStakeRadioButton).click({ force: true });
|
||||
cy.get(tokenAmountInputBox).type(4);
|
||||
cy.contains('Waiting for next epoch to start', { timeout: 10000 });
|
||||
cy.get(staking.tokenInputSubmit)
|
||||
cy.get(tokenSubmitButton)
|
||||
.should('be.disabled', { timeout: 8000 })
|
||||
.and('contain', `Remove 4 $VEGA tokens at the end of epoch`)
|
||||
.and('be.visible');
|
||||
@ -213,22 +210,22 @@ context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
cy.vega_wallet_check_unstaked_value_is('3.000000000000000000');
|
||||
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_add_stake('2');
|
||||
cy.vega_wallet_check_unstaked_value_is('1.000000000000000000');
|
||||
cy.vega_wallet_check_validator_staked_value_is(
|
||||
vega_wallet_check_validator_staked_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.navigate_to('staking');
|
||||
cy.staking_page_disassociate_all_tokens();
|
||||
cy.ethereum_wallet_check_associated_vega_key_is_no_longer_showing(
|
||||
vegaWalletPublicKeyShort
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('0.0');
|
||||
cy.vega_wallet_check_associated_value_is('0.000000000000000000');
|
||||
cy.vega_wallet_check_validator_no_longer_showing(this.validatorName);
|
||||
vega_wallet_check_validator_no_longer_showing(this.validatorName);
|
||||
});
|
||||
|
||||
it('Disassociating some tokens - prioritizes unstaked tokens', function () {
|
||||
@ -236,19 +233,19 @@ context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
cy.vega_wallet_check_unstaked_value_is('3.000000000000000000');
|
||||
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.get(staking.validatorNames).contains(this.validatorName).click();
|
||||
cy.get(validatorList).contains(this.validatorName).click();
|
||||
|
||||
cy.staking_validator_page_add_stake('2');
|
||||
cy.vega_wallet_check_unstaked_value_is('1.000000000000000000');
|
||||
cy.vega_wallet_check_validator_staked_value_is(
|
||||
vega_wallet_check_validator_staked_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.navigate_to('staking');
|
||||
cy.staking_page_disassociate_tokens('1');
|
||||
cy.ethereum_wallet_check_associated_value_is('2.0');
|
||||
cy.vega_wallet_check_associated_value_is('2.000000000000000000');
|
||||
cy.vega_wallet_check_validator_staked_value_is(
|
||||
vega_wallet_check_validator_staked_value_is(
|
||||
this.validatorName,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
@ -261,78 +258,78 @@ context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
cy.staking_validator_page_check_stake_next_epoch_value = (expectedVal) => {
|
||||
cy.highlight(
|
||||
`Checking Staking Page - Validator Stake Next Epoch Value is ${expectedVal}`
|
||||
);
|
||||
cy.get(staking.stakeNextEpochValue, { timeout: 10000 })
|
||||
.contains(expectedVal, { timeout: 10000 })
|
||||
.should('be.visible');
|
||||
};
|
||||
|
||||
cy.staking_validator_page_check_stake_this_epoch_value = (expectedVal) => {
|
||||
cy.highlight(
|
||||
`Checking Staking Page - Validator Stake This Epoch Value is ${expectedVal}`
|
||||
);
|
||||
cy.get(staking.stakeThisEpochValue, { timeout: 10000 })
|
||||
.contains(expectedVal, { timeout: 10000 })
|
||||
.should('be.visible');
|
||||
};
|
||||
|
||||
cy.vega_wallet_check_validator_stake_next_epoch_value_is = (
|
||||
validatorName,
|
||||
expectedVal
|
||||
) => {
|
||||
cy.highlight(
|
||||
`Checking vega wallet - Stake Next Epoch Value for ${validatorName} is ${expectedVal}`
|
||||
);
|
||||
cy.get(wallet.vegawallet).within(() => {
|
||||
cy.contains(`${validatorName} (Next epoch)`, { timeout: 40000 })
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
};
|
||||
|
||||
cy.vega_wallet_check_validator_stake_this_epoch_value_is = (
|
||||
validatorName,
|
||||
expectedVal
|
||||
) => {
|
||||
cy.highlight(
|
||||
`Checking vega wallet - Stake This Epoch Value for ${validatorName} is ${expectedVal}`
|
||||
);
|
||||
cy.get(wallet.vegawallet).within(() => {
|
||||
cy.contains(`${validatorName} (This Epoch)`, { timeout: 40000 })
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
};
|
||||
|
||||
cy.vega_wallet_check_validator_no_longer_showing = (validatorName) => {
|
||||
cy.highlight(
|
||||
`Checking Validator and therefore stake removed for ${validatorName}`
|
||||
);
|
||||
cy.get(wallet.vegawallet).within(() => {
|
||||
cy.contains(`${validatorName}`, { timeout: 40000 }).should('not.exist', {
|
||||
timeout: 40000,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
cy.vega_wallet_check_validator_staked_value_is = (
|
||||
validatorName,
|
||||
expectedVal
|
||||
) => {
|
||||
cy.highlight(
|
||||
`Checking Validator Stake Value for ${validatorName} is ${expectedVal}`
|
||||
);
|
||||
cy.get(wallet.vegawallet).within(() => {
|
||||
cy.contains(`${validatorName}`, { timeout: 40000 })
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
function staking_validator_page_check_stake_next_epoch_value(expectedVal) {
|
||||
cy.highlight(
|
||||
`Checking Staking Page - Validator Stake Next Epoch Value is ${expectedVal}`
|
||||
);
|
||||
cy.get(stakeNextEpochValue, { timeout: 10000 })
|
||||
.contains(expectedVal, { timeout: 10000 })
|
||||
.should('be.visible');
|
||||
}
|
||||
|
||||
function staking_validator_page_check_stake_this_epoch_value(expectedVal) {
|
||||
cy.highlight(
|
||||
`Checking Staking Page - Validator Stake This Epoch Value is ${expectedVal}`
|
||||
);
|
||||
cy.get(stakeNextEpochValue, { timeout: 10000 })
|
||||
.contains(expectedVal, { timeout: 10000 })
|
||||
.should('be.visible');
|
||||
}
|
||||
|
||||
function vega_wallet_check_validator_stake_next_epoch_value_is(
|
||||
validatorName,
|
||||
expectedVal
|
||||
) {
|
||||
cy.highlight(
|
||||
`Checking vega wallet - Stake Next Epoch Value for ${validatorName} is ${expectedVal}`
|
||||
);
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.contains(`${validatorName} (Next epoch)`, { timeout: 40000 })
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
}
|
||||
|
||||
function vega_wallet_check_validator_stake_this_epoch_value_is(
|
||||
validatorName,
|
||||
expectedVal
|
||||
) {
|
||||
cy.highlight(
|
||||
`Checking vega wallet - Stake This Epoch Value for ${validatorName} is ${expectedVal}`
|
||||
);
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.contains(`${validatorName} (This Epoch)`, { timeout: 40000 })
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
}
|
||||
|
||||
function vega_wallet_check_validator_no_longer_showing(validatorName) {
|
||||
cy.highlight(
|
||||
`Checking Validator and therefore stake removed for ${validatorName}`
|
||||
);
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.contains(`${validatorName}`, { timeout: 40000 }).should('not.exist', {
|
||||
timeout: 40000,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function vega_wallet_check_validator_staked_value_is(
|
||||
validatorName,
|
||||
expectedVal
|
||||
) {
|
||||
cy.highlight(
|
||||
`Checking Validator Stake Value for ${validatorName} is ${expectedVal}`
|
||||
);
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.contains(`${validatorName}`, { timeout: 40000 })
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
}
|
||||
|
@ -1,118 +1,98 @@
|
||||
/// <reference types="cypress" />
|
||||
import navigation from '../../locators/navigation.locators';
|
||||
import staking from '../../locators/staking.locators';
|
||||
import wallet from '../../locators/wallet.locators';
|
||||
import '../../support/staking.functions';
|
||||
import '../../support/vega-wallet.functions';
|
||||
import '../../support/eth-wallet.functions';
|
||||
import '../../support/wallet-teardown.functions';
|
||||
const pageSpinner = 'splash-loader';
|
||||
const menuBar = 'nav';
|
||||
const validatorList = '[data-testid="node-list-item-name"]';
|
||||
|
||||
const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort');
|
||||
|
||||
context('Staking Tab - with eth and vega wallets connected', function () {
|
||||
before('visit staking tab and connect vega wallet', function () {
|
||||
cy.vega_wallet_import();
|
||||
cy.visit('/');
|
||||
cy.get(navigation.section, { timeout: 20000 }).should('be.visible');
|
||||
cy.vega_wallet_connect();
|
||||
cy.vega_wallet_set_specified_approval_amount('1000');
|
||||
cy.reload();
|
||||
cy.get(navigation.section, { timeout: 20000 }).should('be.visible');
|
||||
cy.ethereum_wallet_connect();
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.get(navigation.spinner, { timeout: 20000 }).should('not.exist');
|
||||
cy.get(staking.validatorNames).first().invoke('text').as('validatorName');
|
||||
});
|
||||
|
||||
describe('Eth wallet - contains VEGA tokens', function () {
|
||||
beforeEach(
|
||||
'teardown wallet & drill into a specific validator',
|
||||
function () {
|
||||
cy.vega_wallet_teardown();
|
||||
cy.get(navigation.staking).first().click();
|
||||
cy.get(navigation.spinner, { timeout: 20000 }).should('not.exist');
|
||||
}
|
||||
);
|
||||
|
||||
it('Able to associate tokens - from staking page', function () {
|
||||
cy.staking_page_associate_tokens('2');
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('2.0');
|
||||
cy.vega_wallet_check_associated_value_is('2.000000000000000000');
|
||||
cy.vega_wallet_check_unstaked_value_is('2.000000000000000000');
|
||||
context(
|
||||
'Token association flow - with eth and vega wallets connected',
|
||||
function () {
|
||||
before('visit staking tab and connect vega wallet', function () {
|
||||
cy.vega_wallet_import();
|
||||
cy.visit('/');
|
||||
cy.get(menuBar, { timeout: 20000 }).should('be.visible');
|
||||
cy.vega_wallet_connect();
|
||||
cy.vega_wallet_set_specified_approval_amount('1000');
|
||||
cy.reload();
|
||||
cy.get(menuBar, { timeout: 20000 }).should('be.visible');
|
||||
cy.ethereum_wallet_connect();
|
||||
cy.navigate_to('staking');
|
||||
cy.get(pageSpinner, { timeout: 20000 }).should('not.exist');
|
||||
cy.get(validatorList).first().invoke('text').as('validatorName');
|
||||
});
|
||||
|
||||
it('Able to disassociate tokens - from staking page', function () {
|
||||
cy.staking_page_associate_tokens('2');
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'2.000000000000000000'
|
||||
describe('Eth wallet - contains VEGA tokens', function () {
|
||||
beforeEach(
|
||||
'teardown wallet & drill into a specific validator',
|
||||
function () {
|
||||
cy.vega_wallet_teardown();
|
||||
cy.navigate_to('staking');
|
||||
cy.get(pageSpinner, { timeout: 20000 }).should('not.exist');
|
||||
}
|
||||
);
|
||||
cy.vega_wallet_check_associated_value_is('2.000000000000000000');
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.staking_page_disassociate_tokens('1');
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'1.000000000000000000'
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('1.0');
|
||||
cy.vega_wallet_check_associated_value_is('1.000000000000000000');
|
||||
});
|
||||
|
||||
it('Able to access associate token form - from eth wallet', function () {
|
||||
cy.get(wallet.ethWallet).within(() =>
|
||||
cy.get(wallet.ethWalletAssociate).click()
|
||||
);
|
||||
cy.get(staking.stakeAssociateWalletRadio, { timeout: 30000 }).should(
|
||||
'be.enabled'
|
||||
);
|
||||
});
|
||||
it('Able to associate tokens', function () {
|
||||
cy.staking_page_associate_tokens('2');
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('2.0');
|
||||
cy.vega_wallet_check_associated_value_is('2.000000000000000000');
|
||||
cy.vega_wallet_check_unstaked_value_is('2.000000000000000000');
|
||||
});
|
||||
|
||||
it('Able to access disassociate token form - from eth wallet', function () {
|
||||
cy.get(wallet.ethWallet).within(() =>
|
||||
cy.get(wallet.ethWalletDisassociate).click()
|
||||
);
|
||||
cy.get(staking.stakeAssociateWalletRadio, { timeout: 30000 }).should(
|
||||
'be.enabled'
|
||||
);
|
||||
});
|
||||
it('Able to disassociate tokens', function () {
|
||||
cy.staking_page_associate_tokens('2');
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'2.000000000000000000'
|
||||
);
|
||||
cy.vega_wallet_check_associated_value_is('2.000000000000000000');
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.staking_page_disassociate_tokens('1');
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'1.000000000000000000'
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('1.0');
|
||||
cy.vega_wallet_check_associated_value_is('1.000000000000000000');
|
||||
});
|
||||
|
||||
it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () {
|
||||
cy.staking_page_associate_tokens('1001', true);
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'1,001.000000000000000000'
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('1,001.00');
|
||||
cy.vega_wallet_check_associated_value_is('1,001.000000000000000000');
|
||||
});
|
||||
it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () {
|
||||
cy.staking_page_associate_tokens('1001', true);
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'1,001.000000000000000000'
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('1,001.00');
|
||||
cy.vega_wallet_check_associated_value_is('1,001.000000000000000000');
|
||||
});
|
||||
|
||||
it('Able to disassociate a partial amount of tokens currently associated', function () {
|
||||
cy.staking_page_associate_tokens('2');
|
||||
cy.vega_wallet_check_associated_value_is('2.000000000000000000');
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.staking_page_disassociate_tokens('1');
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'1.000000000000000000'
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('1.0');
|
||||
cy.vega_wallet_check_associated_value_is('1.000000000000000000');
|
||||
});
|
||||
it('Able to disassociate a partial amount of tokens currently associated', function () {
|
||||
cy.staking_page_associate_tokens('2');
|
||||
cy.vega_wallet_check_associated_value_is('2.000000000000000000');
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.staking_page_disassociate_tokens('1');
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is(
|
||||
vegaWalletPublicKeyShort,
|
||||
'1.000000000000000000'
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('1.0');
|
||||
cy.vega_wallet_check_associated_value_is('1.000000000000000000');
|
||||
});
|
||||
|
||||
it('Able to disassociate all tokens', function () {
|
||||
cy.staking_page_associate_tokens('2');
|
||||
cy.vega_wallet_check_associated_value_is('2.000000000000000000');
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.staking_page_disassociate_all_tokens();
|
||||
cy.ethereum_wallet_check_associated_vega_key_is_no_longer_showing(
|
||||
vegaWalletPublicKeyShort
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('0.0');
|
||||
cy.vega_wallet_check_associated_value_is('0.000000000000000000');
|
||||
it('Able to disassociate all tokens', function () {
|
||||
cy.staking_page_associate_tokens('2');
|
||||
cy.vega_wallet_check_associated_value_is('2.000000000000000000');
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
cy.staking_page_disassociate_all_tokens();
|
||||
cy.ethereum_wallet_check_associated_vega_key_is_no_longer_showing(
|
||||
vegaWalletPublicKeyShort
|
||||
);
|
||||
cy.ethereum_wallet_check_associated_value_is('0.0');
|
||||
cy.vega_wallet_check_associated_value_is('0.000000000000000000');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -1,30 +1,21 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import governance from '../locators/governance.locators';
|
||||
const noProposals = '[data-testid="no-proposals"]';
|
||||
|
||||
context('Governance Page - verify elements on page', function () {
|
||||
before('navigate to governance page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.governance).click();
|
||||
});
|
||||
cy.visit('/').navigate_to('governance');
|
||||
});
|
||||
|
||||
describe('with no network change proposals', function () {
|
||||
it('should have governance tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.governance).should('have.attr', 'aria-current');
|
||||
});
|
||||
cy.verify_tab_highlighted('governance');
|
||||
});
|
||||
|
||||
it('should have GOVERNANCE header visible', function () {
|
||||
cy.get(governance.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Governance');
|
||||
cy.verify_page_header('Governance');
|
||||
});
|
||||
|
||||
it('should have information box visible', function () {
|
||||
cy.get(governance.noProposals)
|
||||
cy.get(noProposals)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'There are no active network change proposals');
|
||||
});
|
||||
|
@ -1,5 +1,24 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import home from '../locators/home.locators';
|
||||
const navSection = 'nav';
|
||||
const navHome = '[href="/"]';
|
||||
const navVesting = '[href="/vesting"]';
|
||||
const navStaking = '[href="/staking"]';
|
||||
const navRewards = '[href="/rewards"]';
|
||||
const navWithdraw = '[href="/withdraw"]';
|
||||
const navGovernance = '[href="/governance"]';
|
||||
|
||||
const tokenDetailsTable = '.token-details';
|
||||
const address = '[data-testid="token-address"]';
|
||||
const contract = '[data-testid="token-contract"]';
|
||||
const totalSupply = '[data-testid="total-supply"]';
|
||||
const circulatingSupply = '[data-testid="circulating-supply"]';
|
||||
const staked = '[data-testid="staked"]';
|
||||
const tranchesLink = '[data-testid="tranches-link"]';
|
||||
const redeemBtn = '[data-testid="check-vesting-page-btn"]';
|
||||
const getVegaWalletLink = '[data-testid="get-vega-wallet-link"]';
|
||||
const associateVegaLink =
|
||||
'[data-testid="associate-vega-tokens-link-on-homepage"]';
|
||||
const stakingBtn = '[data-testid="staking-button-on-homepage"]';
|
||||
const governanceBtn = '[data-testid="governance-button-on-homepage"]';
|
||||
|
||||
const vegaTokenAddress = Cypress.env('vegaTokenAddress');
|
||||
const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
|
||||
@ -11,111 +30,111 @@ context('Home Page - verify elements on page', function () {
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
before('wait for page to load', function () {
|
||||
cy.get(navigation.section, { timeout: 10000 }).should('be.visible');
|
||||
cy.get(navSection, { timeout: 10000 }).should('be.visible');
|
||||
});
|
||||
|
||||
describe('Navigation tabs', function () {
|
||||
it('should have HOME tab', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.home).should('be.visible');
|
||||
cy.get(navSection).within(() => {
|
||||
cy.get(navHome).should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have VESTING tab', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.vesting).should('be.visible');
|
||||
cy.get(navSection).within(() => {
|
||||
cy.get(navVesting).should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have STAKING tab', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.staking).should('be.visible');
|
||||
cy.get(navSection).within(() => {
|
||||
cy.get(navStaking).should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have REWARDS tab', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.rewards).should('be.visible');
|
||||
cy.get(navSection).within(() => {
|
||||
cy.get(navRewards).should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have WITHDRAW tab', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.withdraw).should('be.visible');
|
||||
cy.get(navSection).within(() => {
|
||||
cy.get(navWithdraw).should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have GOVERNANCE tab', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.governance).should('be.visible');
|
||||
cy.get(navSection).within(() => {
|
||||
cy.get(navGovernance).should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('THE $VEGA TOKEN table', function () {
|
||||
it('should have TOKEN ADDRESS', function () {
|
||||
cy.get(home.tokenDetailsTable).within(() => {
|
||||
cy.get(home.address)
|
||||
cy.get(tokenDetailsTable).within(() => {
|
||||
cy.get(address)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.should('be.equal', vegaTokenAddress);
|
||||
});
|
||||
});
|
||||
it('should have VESTING CONTRACT', function () {
|
||||
cy.get(home.tokenDetailsTable).within(() => {
|
||||
cy.get(home.contract)
|
||||
cy.get(tokenDetailsTable).within(() => {
|
||||
cy.get(contract)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.should('be.equal', vegaTokenContractAddress);
|
||||
});
|
||||
});
|
||||
it('should have TOTAL SUPPLY', function () {
|
||||
cy.get(home.tokenDetailsTable).within(() => {
|
||||
cy.get(home.totalSupply).should('be.visible');
|
||||
cy.get(tokenDetailsTable).within(() => {
|
||||
cy.get(totalSupply).should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have CIRCULATING SUPPLY', function () {
|
||||
cy.get(home.tokenDetailsTable).within(() => {
|
||||
cy.get(home.circulatingSupply).should('be.visible');
|
||||
cy.get(tokenDetailsTable).within(() => {
|
||||
cy.get(circulatingSupply).should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have STAKED $VEGA', function () {
|
||||
cy.get(home.tokenDetailsTable).within(() => {
|
||||
cy.get(home.staked).should('be.visible');
|
||||
cy.get(tokenDetailsTable).within(() => {
|
||||
cy.get(staked).should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('links and buttons', function () {
|
||||
it('should have TRANCHES link', function () {
|
||||
cy.get(home.tranchesLink)
|
||||
cy.get(tranchesLink)
|
||||
.should('be.visible')
|
||||
.and('have.attr', 'href')
|
||||
.and('equal', '/tranches');
|
||||
});
|
||||
it('should have REDEEM button', function () {
|
||||
cy.get(home.redeemBtn)
|
||||
cy.get(redeemBtn)
|
||||
.should('be.visible')
|
||||
.parent()
|
||||
.should('have.attr', 'href')
|
||||
.and('equal', '/vesting');
|
||||
});
|
||||
it('should have GET VEGA WALLET link', function () {
|
||||
cy.get(home.getVegaWalletLink)
|
||||
cy.get(getVegaWalletLink)
|
||||
.should('be.visible')
|
||||
.and('have.attr', 'href')
|
||||
.and('equal', 'https://vega.xyz/wallet');
|
||||
});
|
||||
it('should have ASSOCIATE VEGA TOKENS link', function () {
|
||||
cy.get(home.associateVegaLink)
|
||||
cy.get(associateVegaLink)
|
||||
.should('be.visible')
|
||||
.and('have.attr', 'href')
|
||||
.and('equal', '/staking/associate');
|
||||
});
|
||||
it('should have STAKING button', function () {
|
||||
cy.get(home.stakingBtn)
|
||||
cy.get(stakingBtn)
|
||||
.should('be.visible')
|
||||
.parent()
|
||||
.should('have.attr', 'href')
|
||||
.and('equal', '/staking');
|
||||
});
|
||||
it('should have GOVERNANCE button', function () {
|
||||
cy.get(home.governanceBtn)
|
||||
cy.get(governanceBtn)
|
||||
.should('be.visible')
|
||||
.parent()
|
||||
.should('have.attr', 'href')
|
||||
|
@ -1,30 +1,22 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import rewards from '../locators/rewards.locators';
|
||||
const connectToVegaBtn = '[data-testid="connect-to-vega-wallet-btn"]';
|
||||
const warning = '[data-testid="callout"]';
|
||||
|
||||
context('Rewards Page - verify elements on page', function () {
|
||||
before('navigate to rewards page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.rewards).click();
|
||||
});
|
||||
cy.visit('/').navigate_to('rewards');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
it('should have REWARDS tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.rewards).should('have.attr', 'aria-current');
|
||||
});
|
||||
cy.verify_tab_highlighted('rewards');
|
||||
});
|
||||
|
||||
it('should have rewards header visible', function () {
|
||||
cy.get(rewards.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Rewards');
|
||||
cy.verify_page_header('Rewards');
|
||||
});
|
||||
|
||||
it('should have epoch warning', function () {
|
||||
cy.get(rewards.warning)
|
||||
cy.get(warning)
|
||||
.should('be.visible')
|
||||
.and(
|
||||
'have.text',
|
||||
@ -33,7 +25,7 @@ context('Rewards Page - verify elements on page', function () {
|
||||
});
|
||||
|
||||
it('should have connect Vega wallet button', function () {
|
||||
cy.get(rewards.connectToVegaBtn)
|
||||
cy.get(connectToVegaBtn)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Vega wallet');
|
||||
});
|
||||
|
@ -1,31 +1,30 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import staking from '../locators/staking.locators';
|
||||
const guideLink = '[data-testid="staking-guide-link"]';
|
||||
const step1 = '[data-testid="staking-step-1"]';
|
||||
const step2 = '[data-testid="staking-step-2"]';
|
||||
const step3 = '[data-testid="staking-step-3"]';
|
||||
const sectionHeader = 'h2';
|
||||
const connectToEthBtn = '[data-testid="connect-to-eth-btn"]';
|
||||
const connectToVegaBtn = '[data-testid="connect-to-vega-wallet-btn"]';
|
||||
const link = '[data-testid="link"]';
|
||||
const warning = '[data-testid="callout"]';
|
||||
|
||||
context('Staking Page - verify elements on page', function () {
|
||||
before('navigate to staking page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.staking).click();
|
||||
});
|
||||
cy.visit('/').navigate_to('staking');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
describe('description section', function () {
|
||||
it('should have staking tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.staking).should('have.attr', 'aria-current');
|
||||
});
|
||||
cy.verify_tab_highlighted('staking');
|
||||
});
|
||||
|
||||
it('should have STAKING ON VEGA header visible', function () {
|
||||
cy.get(staking.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Staking on Vega');
|
||||
cy.verify_page_header('Staking on Vega');
|
||||
});
|
||||
|
||||
it('should have Staking Guide link visible', function () {
|
||||
cy.get(staking.guideLink)
|
||||
cy.get(guideLink)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Read more about staking on Vega')
|
||||
.and(
|
||||
@ -38,16 +37,16 @@ context('Staking Page - verify elements on page', function () {
|
||||
|
||||
describe('step 1 section', function () {
|
||||
it('should have header visible', function () {
|
||||
cy.get(staking.step1).within(() => {
|
||||
cy.get(staking.sectionHeader)
|
||||
cy.get(step1).within(() => {
|
||||
cy.get(sectionHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Step 1. Connect to a Vega Wallet');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have text visible', function () {
|
||||
cy.get(staking.step1).within(() => {
|
||||
cy.get(staking.link)
|
||||
cy.get(step1).within(() => {
|
||||
cy.get(link)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Vega Wallet')
|
||||
.and('have.attr', 'href', 'https://vega.xyz/wallet');
|
||||
@ -55,16 +54,16 @@ context('Staking Page - verify elements on page', function () {
|
||||
});
|
||||
|
||||
it('should have connect to eth button visible', function () {
|
||||
cy.get(staking.step1).within(() => {
|
||||
cy.get(staking.connectToEthBtn)
|
||||
cy.get(step1).within(() => {
|
||||
cy.get(connectToEthBtn)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Ethereum wallet');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have connect to vega button visible', function () {
|
||||
cy.get(staking.step1).within(() => {
|
||||
cy.get(staking.connectToVegaBtn)
|
||||
cy.get(step1).within(() => {
|
||||
cy.get(connectToVegaBtn)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Vega wallet');
|
||||
});
|
||||
@ -73,16 +72,16 @@ context('Staking Page - verify elements on page', function () {
|
||||
|
||||
describe('step 2 section', function () {
|
||||
it('should have header visible', function () {
|
||||
cy.get(staking.step2).within(() => {
|
||||
cy.get(staking.sectionHeader)
|
||||
cy.get(step2).within(() => {
|
||||
cy.get(sectionHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Step 2. Associate tokens with a Vega Wallet');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have warning visible', function () {
|
||||
cy.get(staking.step2).within(() => {
|
||||
cy.get(staking.warning)
|
||||
cy.get(step2).within(() => {
|
||||
cy.get(warning)
|
||||
.should('be.visible')
|
||||
.and(
|
||||
'have.text',
|
||||
@ -94,8 +93,8 @@ context('Staking Page - verify elements on page', function () {
|
||||
|
||||
describe('step 3 section', function () {
|
||||
it('should have header visible', function () {
|
||||
cy.get(staking.step3).within(() => {
|
||||
cy.get(staking.sectionHeader)
|
||||
cy.get(step3).within(() => {
|
||||
cy.get(sectionHeader)
|
||||
.should('be.visible')
|
||||
.and(
|
||||
'have.text',
|
||||
|
@ -1,34 +1,26 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import vesting from '../locators/vesting.locators';
|
||||
const connectPrompt = '[data-testid="eth-connect-prompt"]';
|
||||
const connectButton = '[data-testid="connect-to-eth-btn"]';
|
||||
|
||||
context('Vesting Page - verify elements on page', function () {
|
||||
before('navigate to vesting page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.vesting).click();
|
||||
});
|
||||
cy.visit('/').navigate_to('vesting');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
it('should have vesting tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.vesting).should('have.attr', 'aria-current');
|
||||
});
|
||||
cy.verify_tab_highlighted('vesting');
|
||||
});
|
||||
|
||||
it('should have VESTING header visible', function () {
|
||||
cy.get(vesting.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Vesting');
|
||||
cy.verify_page_header('Vesting');
|
||||
});
|
||||
|
||||
it('should have connect Eth wallet info', function () {
|
||||
cy.get(vesting.connectPrompt).should('be.visible');
|
||||
cy.get(connectPrompt).should('be.visible');
|
||||
});
|
||||
|
||||
it('should have connect Eth wallet button', function () {
|
||||
cy.get(vesting.connectButton)
|
||||
cy.get(connectButton)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Ethereum wallet');
|
||||
});
|
||||
|
251
apps/token-e2e/src/integration/wallet-eth.cy.js
Normal file
251
apps/token-e2e/src/integration/wallet-eth.cy.js
Normal file
@ -0,0 +1,251 @@
|
||||
const walletContainer = '[data-testid="ethereum-wallet"]';
|
||||
const walletHeader = '[data-testid="wallet-header"] h1';
|
||||
const connectToEthButton = '[data-testid="connect-to-eth-wallet-button"]';
|
||||
const connectorList = '[data-testid="web3-connector-list"]';
|
||||
const associate = '[href="/staking/associate"]';
|
||||
const disassociate = '[href="/staking/disassociate"]';
|
||||
const disconnect = '[data-testid="disconnect-from-eth-wallet-button"]';
|
||||
const accountNo = '[data-testid="ethereum-account-truncated"]';
|
||||
const currencyTitle = '[data-testid="currency-title"]';
|
||||
const currencyValue = '[data-testid="currency-value"]';
|
||||
const vegaInVesting = '[data-testid="vega-in-vesting-contract"]';
|
||||
const vegaInWallet = '[data-testid="vega-in-wallet"]';
|
||||
const progressBar = '[data-testid="progress-bar"]';
|
||||
const currencyLocked = '[data-testid="currency-locked"]';
|
||||
const currencyUnlocked = '[data-testid="currency-unlocked"]';
|
||||
const dialog = '[role="dialog"]';
|
||||
const dialogHeader = '[data-testid="dialog-title"]';
|
||||
const dialogCloseBtn = '[data-testid="dialog-close"]';
|
||||
|
||||
context('Ethereum Wallet - verify elements on widget', function () {
|
||||
before('visit token home page', function () {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
before('wait for widget to load', function () {
|
||||
cy.get(walletContainer, { timeout: 10000 }).should('be.visible');
|
||||
});
|
||||
|
||||
it('should have ETHEREUM KEY header visible', function () {
|
||||
cy.get(walletContainer).within(() => {
|
||||
cy.get(walletHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Ethereum key');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have Connect Ethereum button visible', function () {
|
||||
cy.get(walletContainer).within(() => {
|
||||
cy.get(connectToEthButton)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Ethereum wallet to associate $VEGA');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Connect Ethereum clicked', function () {
|
||||
before('', function () {
|
||||
cy.get(connectToEthButton).click();
|
||||
});
|
||||
|
||||
it('should have Connect Ethereum header visible', function () {
|
||||
cy.get(dialog).within(() => {
|
||||
cy.get(dialogHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect to your Ethereum wallet');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have connector list visible', function () {
|
||||
const connectList = [
|
||||
'Unknown',
|
||||
'MetaMask, Brave or other injected web wallet',
|
||||
'WalletConnect',
|
||||
];
|
||||
cy.get(connectorList).within(() => {
|
||||
cy.get('button').each(($btn, i) => {
|
||||
cy.wrap($btn).should('be.visible').and('have.text', connectList[i]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
after('close popup', function () {
|
||||
cy.get(dialog)
|
||||
.within(() => {
|
||||
cy.get(dialogCloseBtn).click();
|
||||
})
|
||||
.should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Ethereum wallet connected', function () {
|
||||
before('connect to Ethereum wallet', function () {
|
||||
cy.ethereum_wallet_connect();
|
||||
});
|
||||
|
||||
it('should have ETHEREUM KEY header visible', function () {
|
||||
cy.get(walletContainer).within(() => {
|
||||
cy.get(walletHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Ethereum key');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have account number visible', function () {
|
||||
cy.get(walletContainer).within(() => {
|
||||
cy.get(accountNo)
|
||||
.should('be.visible')
|
||||
.and('have.text', Cypress.env('ethWalletPublicKeyTruncated'));
|
||||
});
|
||||
});
|
||||
|
||||
it('should have Associate button visible', function () {
|
||||
cy.get(walletContainer).within(() => {
|
||||
cy.get(associate).should('be.visible').and('have.text', 'Associate');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have Disassociate button visible', function () {
|
||||
cy.get(walletContainer).within(() => {
|
||||
cy.get(disassociate)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Disassociate');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have Disconnect button visible', function () {
|
||||
cy.get(walletContainer).within(() => {
|
||||
cy.get(disconnect).should('be.visible').and('have.text', 'Disconnect');
|
||||
});
|
||||
});
|
||||
|
||||
describe('VEGA IN VESTING CONTRACT', function () {
|
||||
it('should have currency title visible', function () {
|
||||
cy.get(vegaInVesting).within(() => {
|
||||
cy.get(currencyTitle)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'VEGAIn vesting contract');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have currency value visible', function () {
|
||||
cy.get(vegaInVesting).within(() => {
|
||||
cy.get(currencyValue)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.should('match', /\d{0,3}(,\d{3})*\.\d{18}$/);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have progress bar visible', function () {
|
||||
cy.get(vegaInVesting).within(() => {
|
||||
cy.get(progressBar).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have locked currency visible', function () {
|
||||
cy.get(vegaInVesting).within(() => {
|
||||
cy.get(currencyLocked)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.should('match', /\d{0,3}(,\d{3})*\.\d{2}$/);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have unlocked currency visible', function () {
|
||||
cy.get(vegaInVesting).within(() => {
|
||||
cy.get(currencyUnlocked)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.should('match', /\d{0,3}(,\d{3})*\.\d{2}$/);
|
||||
});
|
||||
});
|
||||
|
||||
it('should match total & locked/unlocked currency value', function () {
|
||||
cy.get(vegaInVesting)
|
||||
.within(() => {
|
||||
cy.get(currencyValue)
|
||||
.invoke('text')
|
||||
.convert_token_value_to_number()
|
||||
.as('value');
|
||||
cy.get(currencyLocked)
|
||||
.invoke('text')
|
||||
.convert_token_value_to_number()
|
||||
.as('locked');
|
||||
cy.get(currencyUnlocked)
|
||||
.invoke('text')
|
||||
.convert_token_value_to_number()
|
||||
.as('unlocked');
|
||||
})
|
||||
.then(function () {
|
||||
expect(this.value).to.equal(this.locked + this.unlocked);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('VEGA IN WALLET', function () {
|
||||
it('should have currency title visible', function () {
|
||||
cy.get(vegaInWallet).within(() => {
|
||||
cy.get(currencyTitle)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'VEGAIn Wallet');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have currency value visible', function () {
|
||||
cy.get(vegaInWallet).within(() => {
|
||||
cy.get(currencyValue)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.should('match', /\d{0,3}(,\d{3})*\.\d{18}$/);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have progress bar visible', function () {
|
||||
cy.get(vegaInWallet).within(() => {
|
||||
cy.get(progressBar).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have locked currency visible', function () {
|
||||
cy.get(vegaInWallet).within(() => {
|
||||
cy.get(currencyLocked)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.should('match', /\d{0,3}(,\d{3})*\.\d{2}$/);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have unlocked currency visible', function () {
|
||||
cy.get(vegaInWallet).within(() => {
|
||||
cy.get(currencyUnlocked)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.should('match', /\d{0,3}(,\d{3})*\.\d{2}$/);
|
||||
});
|
||||
});
|
||||
|
||||
it('should match total & locked/unlocked currency value', function () {
|
||||
cy.get(vegaInWallet)
|
||||
.within(() => {
|
||||
cy.get(currencyValue)
|
||||
.invoke('text')
|
||||
.convert_token_value_to_number()
|
||||
.as('value');
|
||||
cy.get(currencyLocked)
|
||||
.invoke('text')
|
||||
.convert_token_value_to_number()
|
||||
.as('locked');
|
||||
cy.get(currencyUnlocked)
|
||||
.invoke('text')
|
||||
.convert_token_value_to_number()
|
||||
.as('unlocked');
|
||||
})
|
||||
.then(function () {
|
||||
expect(this.value).to.equal(this.locked + this.unlocked);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,36 +1,28 @@
|
||||
import navigation from '../locators/navigation.locators';
|
||||
import withdraw from '../locators/withdraw.locators';
|
||||
const connectToVegaBtn = '[data-testid="connect-to-vega-wallet-btn"]';
|
||||
const warning = '[data-testid="callout"]';
|
||||
|
||||
context('Withdraw Page - verify elements on page', function () {
|
||||
before('navigate to withdraw page', function () {
|
||||
cy.visit('/')
|
||||
.get(navigation.section)
|
||||
.within(() => {
|
||||
cy.get(navigation.withdraw).click();
|
||||
});
|
||||
cy.visit('/').navigate_to('withdraw');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
it('should have withdraw tab highlighted', function () {
|
||||
cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation.withdraw).should('have.attr', 'aria-current');
|
||||
});
|
||||
cy.verify_tab_highlighted('withdraw');
|
||||
});
|
||||
|
||||
it('should have WITHDRAW header visible', function () {
|
||||
cy.get(withdraw.pageHeader)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Withdraw');
|
||||
cy.verify_page_header('Withdraw');
|
||||
});
|
||||
|
||||
it('should have connect Vega wallet button', function () {
|
||||
cy.get(withdraw.connectToVegaBtn)
|
||||
cy.get(connectToVegaBtn)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Vega wallet');
|
||||
});
|
||||
|
||||
it('should have withdraw information box', function () {
|
||||
cy.get(withdraw.warning).should('be.visible');
|
||||
cy.get(warning).should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +0,0 @@
|
||||
export default {
|
||||
pageHeader: 'header h1',
|
||||
sectionHeader: 'h2',
|
||||
link: '[data-testid="link"]',
|
||||
warning: '[data-testid="callout"]',
|
||||
connectToVegaBtn: '[data-testid="connect-to-vega-wallet-btn"]',
|
||||
};
|
@ -1,6 +0,0 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
noProposals: '[data-testid="no-proposals"]',
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
export default {
|
||||
tokenDetailsTable: '.token-details',
|
||||
address: '[data-testid="token-address"]',
|
||||
contract: '[data-testid="token-contract"]',
|
||||
totalSupply: '[data-testid="total-supply"]',
|
||||
circulatingSupply: '[data-testid="circulating-supply"]',
|
||||
staked: '[data-testid="staked"]',
|
||||
|
||||
tranchesLink: '[data-testid="tranches-link"]',
|
||||
redeemBtn: '[data-testid="check-vesting-page-btn"]',
|
||||
getVegaWalletLink: '[data-testid="get-vega-wallet-link"]',
|
||||
associateVegaLink: '[data-testid="associate-vega-tokens-link-on-homepage"]',
|
||||
stakingBtn: '[data-testid="staking-button-on-homepage"]',
|
||||
governanceBtn: '[data-testid="governance-button-on-homepage"]',
|
||||
};
|
@ -1,13 +0,0 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
section: 'nav',
|
||||
home: '[href="/"]',
|
||||
vesting: '[href="/vesting"]',
|
||||
staking: '[href="/staking"]',
|
||||
rewards: '[href="/rewards"]',
|
||||
withdraw: '[href="/withdraw"]',
|
||||
governance: '[href="/governance"]',
|
||||
spinner: 'splash-loader',
|
||||
};
|
@ -1,5 +0,0 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
};
|
@ -1,26 +0,0 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
guideLink: '[data-testid="staking-guide-link"]',
|
||||
step1: '[data-testid="staking-step-1"]',
|
||||
step2: '[data-testid="staking-step-2"]',
|
||||
step3: '[data-testid="staking-step-3"]',
|
||||
connectToEthBtn: '[data-testid="connect-to-eth-btn"]',
|
||||
connectToVegaBtn: '[data-testid="connect-to-vega-wallet-btn"]',
|
||||
validatorNames: '[data-testid="node-list-item-name"]',
|
||||
epochEndingText: '[data-testid="epoch-countdown"]',
|
||||
addStakeRadioButton: '[data-testid="add-stake-radio"]',
|
||||
removeStakeRadioButton: '[data-testid="remove-stake-radio"]',
|
||||
tokenAmountInput: '[data-testid="token-amount-input"]',
|
||||
tokenInputApprove: '[data-testid="token-input-approve-button"]',
|
||||
tokenInputSubmit: '[data-testid="token-input-submit-button"]',
|
||||
stakedAmounts: '[data-testid="staked-validator-item"]',
|
||||
stakeNextEpochValue: '[data-testid="stake-next-epoch"]',
|
||||
stakeThisEpochValue: '[data-testid="stake-this-epoch"]',
|
||||
stakeMaximumTokens: '[data-testid="token-amount-use-maximum"]',
|
||||
stakeAssociateWalletRadio: '[data-testid="associate-radio-wallet"]',
|
||||
disassociateButton: '[data-testid="disassociate-tokens-btn"]',
|
||||
associateMoreTokensButton: '[data-testid="associate-more-tokens-btn"]',
|
||||
associateButton: '[data-testid="associate-tokens-btn"]',
|
||||
};
|
@ -1,7 +0,0 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
connectPrompt: '[data-testid="eth-connect-prompt"]',
|
||||
connectButton: '[data-testid="connect-to-eth-btn"]',
|
||||
};
|
@ -1,14 +0,0 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
connectRestForm: '[data-testid="rest-connector-form"]',
|
||||
name: '#wallet',
|
||||
passphrase: '#passphrase',
|
||||
vegawallet: '[data-testid="vega-wallet"]',
|
||||
ethWallet: '[data-testid="ethereum-wallet"]',
|
||||
ethWalletConnectToEth: '[data-testid="connect-to-eth-wallet-button"]',
|
||||
ethWalletConnect: '[data-testid="web3-connector-Unknown"]',
|
||||
ethWalletAssociate: '[href="/staking/associate"]',
|
||||
ethWalletDisassociate: '[href="/staking/disassociate"]',
|
||||
};
|
@ -1,5 +0,0 @@
|
||||
import common from './common.locators';
|
||||
|
||||
export default {
|
||||
...common,
|
||||
};
|
33
apps/token-e2e/src/support/common.functions.js
Normal file
33
apps/token-e2e/src/support/common.functions.js
Normal file
@ -0,0 +1,33 @@
|
||||
Cypress.Commands.add(
|
||||
'convert_token_value_to_number',
|
||||
{ prevSubject: true },
|
||||
(subject) => {
|
||||
return parseFloat(subject.replace(/,/g, ''));
|
||||
}
|
||||
);
|
||||
|
||||
const navigation = {
|
||||
section: 'nav',
|
||||
home: '[href="/"]',
|
||||
vesting: '[href="/vesting"]',
|
||||
staking: '[href="/staking"]',
|
||||
rewards: '[href="/rewards"]',
|
||||
withdraw: '[href="/withdraw"]',
|
||||
governance: '[href="/governance"]',
|
||||
};
|
||||
|
||||
Cypress.Commands.add('navigate_to', (page) => {
|
||||
return cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation[page]).click();
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('verify_tab_highlighted', (page) => {
|
||||
return cy.get(navigation.section).within(() => {
|
||||
cy.get(navigation[page]).should('have.attr', 'aria-current');
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('verify_page_header', (text) => {
|
||||
return cy.get('header h1').should('be.visible').and('have.text', text);
|
||||
});
|
@ -1,51 +0,0 @@
|
||||
import wallet from '../locators/wallet.locators';
|
||||
|
||||
cy.ethereum_wallet_connect = () => {
|
||||
cy.highlight('Connecting Eth Wallet');
|
||||
cy.get(wallet.ethWalletConnectToEth).within(() => {
|
||||
cy.contains('Connect Ethereum wallet to associate $VEGA')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
});
|
||||
cy.get(wallet.ethWalletConnect).click();
|
||||
cy.get(wallet.ethWalletConnect, { timeout: 60000 }).should('not.exist');
|
||||
cy.get(wallet.ethWallet).within(() => {
|
||||
// this check is required since it ensures the wallet is fully (not partially) loaded
|
||||
cy.contains('Locked', { timeout: 15000 }).should('be.visible');
|
||||
});
|
||||
};
|
||||
|
||||
cy.ethereum_wallet_check_associated_value_is = (expectedVal) => {
|
||||
cy.highlight(`Checking Eth Wallet - Associated Value is ${expectedVal}`);
|
||||
cy.get(wallet.ethWallet).within(() => {
|
||||
cy.contains('Associated', { timeout: 20000 })
|
||||
.parent()
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
};
|
||||
|
||||
cy.ethereum_wallet_check_associated_vega_key_value_is = (
|
||||
vegaShortPublicKey,
|
||||
expectedVal
|
||||
) => {
|
||||
cy.highlight(
|
||||
`Checking Eth Wallet - Vega Key Associated Value is ${expectedVal} for key ${vegaShortPublicKey}`
|
||||
);
|
||||
cy.get(wallet.ethWallet).within(() => {
|
||||
cy.contains(vegaShortPublicKey, { timeout: 20000 })
|
||||
.parent()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
};
|
||||
|
||||
cy.ethereum_wallet_check_associated_vega_key_is_no_longer_showing = (
|
||||
vegaShortPublicKey
|
||||
) => {
|
||||
cy.highlight('Checking Eth Wallet - Vega Key Associated is not showing');
|
||||
cy.get(wallet.ethWallet).within(() => {
|
||||
cy.contains(vegaShortPublicKey, { timeout: 20000 }).should('not.exist');
|
||||
});
|
||||
};
|
@ -1,5 +1,11 @@
|
||||
import '@vegaprotocol/cypress';
|
||||
|
||||
import './common.functions.js';
|
||||
import './staking.functions.js';
|
||||
import './wallet-eth.functions.js';
|
||||
import './wallet-teardown.functions.js';
|
||||
import './wallet-vega.functions.js';
|
||||
|
||||
// Hide fetch/XHR requests - They create a lot of noise in command log
|
||||
const app = window.top;
|
||||
if (!app.document.head.querySelector('[data-hide-command-log-request]')) {
|
||||
|
@ -1,11 +1,27 @@
|
||||
import staking from '../locators/staking.locators';
|
||||
const tokenAmountInputBox = '[data-testid="token-amount-input"]';
|
||||
const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
|
||||
const tokenInputApprove = '[data-testid="token-input-approve-button"]';
|
||||
const addStakeRadioButton = '[data-testid="add-stake-radio"]';
|
||||
const removeStakeRadioButton = '[data-testid="remove-stake-radio"]';
|
||||
const ethWalletAssociateButton = '[href="/staking/associate"]';
|
||||
const ethWalletDissociateButton = '[href="/staking/disassociate"]';
|
||||
const associateWalletRadioButton = '[data-testid="associate-radio-wallet"]';
|
||||
const stakeMaximumTokens = '[data-testid="token-amount-use-maximum"]';
|
||||
|
||||
cy.staking_validator_page_add_stake = (stake) => {
|
||||
Cypress.Commands.add('wait_for_begining_of_epoch', () => {
|
||||
cy.highlight(`Waiting for next epoch to start`);
|
||||
cy.contains('Waiting for next epoch to start', { timeout: 10000 }).should(
|
||||
'not.exist'
|
||||
);
|
||||
cy.contains('Waiting for next epoch to start', { timeout: 20000 });
|
||||
});
|
||||
|
||||
Cypress.Commands.add('staking_validator_page_add_stake', (stake) => {
|
||||
cy.highlight(`Adding a stake of ${stake}`);
|
||||
cy.get(staking.addStakeRadioButton).click({ force: true });
|
||||
cy.get(staking.tokenAmountInput).type(stake);
|
||||
cy.contains('Waiting for next epoch to start', { timeout: 10000 });
|
||||
cy.get(staking.tokenInputSubmit, { timeout: 8000 })
|
||||
cy.get(addStakeRadioButton).click({ force: true });
|
||||
cy.get(tokenAmountInputBox).type(stake);
|
||||
cy.wait_for_begining_of_epoch();
|
||||
cy.get(tokenSubmitButton, { timeout: 8000 })
|
||||
.should('be.enabled')
|
||||
.and('contain', `Add ${stake} $VEGA tokens`)
|
||||
.and('be.visible')
|
||||
@ -14,14 +30,14 @@ cy.staking_validator_page_add_stake = (stake) => {
|
||||
'At the beginning of the next epoch your $VEGA will be nominated to the validator',
|
||||
{ timeout: 20000 }
|
||||
).should('be.visible');
|
||||
};
|
||||
});
|
||||
|
||||
cy.staking_validator_page_removeStake = (stake) => {
|
||||
Cypress.Commands.add('staking_validator_page_removeStake', (stake) => {
|
||||
cy.highlight(`Removing a stake of ${stake}`);
|
||||
cy.get(staking.removeStakeRadioButton).click({ force: true });
|
||||
cy.get(staking.tokenAmountInput).type(stake);
|
||||
cy.contains('Waiting for next epoch to start', { timeout: 10000 });
|
||||
cy.get(staking.tokenInputSubmit)
|
||||
cy.get(removeStakeRadioButton).click({ force: true });
|
||||
cy.get(tokenAmountInputBox).type(stake);
|
||||
cy.wait_for_begining_of_epoch();
|
||||
cy.get(tokenSubmitButton)
|
||||
.should('be.enabled', { timeout: 8000 })
|
||||
.and('contain', `Remove ${stake} $VEGA tokens at the end of epoch`)
|
||||
.and('be.visible')
|
||||
@ -29,53 +45,52 @@ cy.staking_validator_page_removeStake = (stake) => {
|
||||
cy.contains(`${stake} $VEGA has been removed from validator`).should(
|
||||
'be.visible'
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
cy.staking_page_associate_tokens = (amount, approve = false) => {
|
||||
cy.highlight(`Associating ${amount} tokens`);
|
||||
cy.get(staking.associateButton).click();
|
||||
cy.get(staking.stakeAssociateWalletRadio, { timeout: 30000 }).click();
|
||||
cy.get(staking.tokenAmountInput, { timeout: 10000 }).type(amount);
|
||||
if (approve) {
|
||||
cy.get(staking.tokenInputApprove, { timeout: 40000 })
|
||||
.should('be.enabled')
|
||||
.click();
|
||||
cy.contains('Approve $VEGA Tokens for staking on Vega').should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Approve $VEGA Tokens for staking on Vega', {
|
||||
timeout: 40000,
|
||||
}).should('not.exist');
|
||||
Cypress.Commands.add(
|
||||
'staking_page_associate_tokens',
|
||||
(amount, approve = false) => {
|
||||
cy.highlight(`Associating ${amount} tokens`);
|
||||
cy.get(ethWalletAssociateButton).first().click();
|
||||
cy.get(associateWalletRadioButton, { timeout: 30000 }).click();
|
||||
cy.get(tokenAmountInputBox, { timeout: 10000 }).type(amount);
|
||||
if (approve) {
|
||||
cy.get(tokenInputApprove, { timeout: 40000 })
|
||||
.should('be.enabled')
|
||||
.click();
|
||||
cy.contains('Approve $VEGA Tokens for staking on Vega').should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Approve $VEGA Tokens for staking on Vega', {
|
||||
timeout: 40000,
|
||||
}).should('not.exist');
|
||||
}
|
||||
cy.get(tokenSubmitButton, { timeout: 40000 }).should('be.enabled').click();
|
||||
cy.contains('can now participate in governance and nominate a validator', {
|
||||
timeout: 60000,
|
||||
}).should('be.visible');
|
||||
}
|
||||
cy.get(staking.tokenInputSubmit, { timeout: 40000 })
|
||||
.should('be.enabled')
|
||||
.click();
|
||||
cy.contains('can now participate in governance and nominate a validator', {
|
||||
timeout: 60000,
|
||||
}).should('be.visible');
|
||||
};
|
||||
);
|
||||
|
||||
cy.staking_page_disassociate_tokens = (amount) => {
|
||||
Cypress.Commands.add('staking_page_disassociate_tokens', (amount) => {
|
||||
cy.highlight(`Disassociating ${amount} tokens via Staking Page`);
|
||||
cy.get(staking.disassociateButton).click();
|
||||
cy.get(staking.stakeAssociateWalletRadio, { timeout: 30000 }).click();
|
||||
cy.get(staking.tokenAmountInput, { timeout: 10000 }).type(amount);
|
||||
cy.get(ethWalletDissociateButton).first().click();
|
||||
cy.get(associateWalletRadioButton, { timeout: 30000 }).click();
|
||||
cy.get(tokenAmountInputBox, { timeout: 10000 }).type(amount);
|
||||
|
||||
cy.get(staking.tokenInputSubmit, { timeout: 40000 })
|
||||
.should('be.enabled')
|
||||
.click();
|
||||
cy.get(tokenSubmitButton, { timeout: 40000 }).should('be.enabled').click();
|
||||
cy.contains(`${amount} $VEGA tokens have been returned to Ethereum wallet`, {
|
||||
timeout: 60000,
|
||||
}).should('be.visible');
|
||||
};
|
||||
});
|
||||
|
||||
cy.staking_page_disassociate_all_tokens = () => {
|
||||
Cypress.Commands.add('staking_page_disassociate_all_tokens', () => {
|
||||
cy.highlight(`Disassociating all tokens via Staking Page`);
|
||||
cy.get(staking.disassociateButton).click();
|
||||
cy.get(staking.stakeAssociateWalletRadio, { timeout: 20000 }).click();
|
||||
cy.get(staking.stakeMaximumTokens, { timeout: 60000 }).click();
|
||||
cy.get(staking.tokenInputSubmit, { timeout: 10000 }).click();
|
||||
cy.get(ethWalletDissociateButton).first().click();
|
||||
cy.get(associateWalletRadioButton, { timeout: 20000 }).click();
|
||||
cy.get(stakeMaximumTokens, { timeout: 60000 }).click();
|
||||
cy.get(tokenSubmitButton, { timeout: 10000 }).click();
|
||||
cy.contains('$VEGA tokens have been returned to Ethereum wallet', {
|
||||
timeout: 60000,
|
||||
}).should('be.visible');
|
||||
};
|
||||
});
|
||||
|
57
apps/token-e2e/src/support/wallet-eth.functions.js
Normal file
57
apps/token-e2e/src/support/wallet-eth.functions.js
Normal file
@ -0,0 +1,57 @@
|
||||
const ethWalletContainer = '[data-testid="ethereum-wallet"]';
|
||||
const connectToEthButton = '[data-testid="connect-to-eth-wallet-button"]';
|
||||
const capsuleWalletConnectButton = '[data-testid="web3-connector-Unknown"]';
|
||||
|
||||
Cypress.Commands.add('ethereum_wallet_connect', () => {
|
||||
cy.highlight('Connecting Eth Wallet');
|
||||
cy.get(connectToEthButton).within(() => {
|
||||
cy.contains('Connect Ethereum wallet to associate $VEGA')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
});
|
||||
cy.get(capsuleWalletConnectButton).click();
|
||||
cy.get(capsuleWalletConnectButton, { timeout: 60000 }).should('not.exist');
|
||||
cy.get(ethWalletContainer).within(() => {
|
||||
// this check is required since it ensures the wallet is fully (not partially) loaded
|
||||
cy.contains('Locked', { timeout: 15000 }).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'ethereum_wallet_check_associated_value_is',
|
||||
(expectedVal) => {
|
||||
cy.highlight(`Checking Eth Wallet - Associated Value is ${expectedVal}`);
|
||||
cy.get(ethWalletContainer).within(() => {
|
||||
cy.contains('Associated', { timeout: 20000 })
|
||||
.parent()
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add(
|
||||
'ethereum_wallet_check_associated_vega_key_value_is',
|
||||
(vegaShortPublicKey, expectedVal) => {
|
||||
cy.highlight(
|
||||
`Checking Eth Wallet - Vega Key Associated Value is ${expectedVal} for key ${vegaShortPublicKey}`
|
||||
);
|
||||
cy.get(ethWalletContainer).within(() => {
|
||||
cy.contains(vegaShortPublicKey, { timeout: 20000 })
|
||||
.parent()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add(
|
||||
'ethereum_wallet_check_associated_vega_key_is_no_longer_showing',
|
||||
(vegaShortPublicKey) => {
|
||||
cy.highlight('Checking Eth Wallet - Vega Key Associated is not showing');
|
||||
cy.get(ethWalletContainer).within(() => {
|
||||
cy.contains(vegaShortPublicKey, { timeout: 20000 }).should('not.exist');
|
||||
});
|
||||
}
|
||||
);
|
@ -64,27 +64,30 @@ Cypress.Commands.add(
|
||||
}
|
||||
);
|
||||
|
||||
cy.vega_wallet_teardown_staking = (stakingBridgeContract) => {
|
||||
cy.highlight('Tearing down staking tokens from vega wallet if present');
|
||||
cy.wrap(
|
||||
stakingBridgeContract.stakeBalance(ethWalletPubKey, vegaWalletPubKey),
|
||||
{
|
||||
timeout: transactionTimeout,
|
||||
log: false,
|
||||
}
|
||||
).then((stake_amount) => {
|
||||
if (String(stake_amount) != '0') {
|
||||
cy.wrap(
|
||||
stakingBridgeContract.removeStake(stake_amount, vegaWalletPubKey),
|
||||
{ timeout: transactionTimeout, log: false }
|
||||
).then((tx) => {
|
||||
cy.wait_for_transaction(tx);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
Cypress.Commands.add(
|
||||
'vega_wallet_teardown_staking',
|
||||
(stakingBridgeContract) => {
|
||||
cy.highlight('Tearing down staking tokens from vega wallet if present');
|
||||
cy.wrap(
|
||||
stakingBridgeContract.stakeBalance(ethWalletPubKey, vegaWalletPubKey),
|
||||
{
|
||||
timeout: transactionTimeout,
|
||||
log: false,
|
||||
}
|
||||
).then((stake_amount) => {
|
||||
if (String(stake_amount) != '0') {
|
||||
cy.wrap(
|
||||
stakingBridgeContract.removeStake(stake_amount, vegaWalletPubKey),
|
||||
{ timeout: transactionTimeout, log: false }
|
||||
).then((tx) => {
|
||||
cy.wait_for_transaction(tx);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
cy.vega_wallet_teardown_vesting = (vestingContract) => {
|
||||
Cypress.Commands.add('vega_wallet_teardown_vesting', (vestingContract) => {
|
||||
cy.highlight('Tearing down vesting tokens from vega wallet if present');
|
||||
cy.wrap(vestingContract.stakeBalance(ethWalletPubKey, vegaWalletPubKey), {
|
||||
timeout: transactionTimeout,
|
||||
@ -99,8 +102,8 @@ cy.vega_wallet_teardown_vesting = (vestingContract) => {
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
cy.wait_for_transaction = (tx) => {
|
||||
Cypress.Commands.add('wait_for_transaction', (tx) => {
|
||||
cy.wrap(tx.wait(1).catch(cy.log), { timeout: transactionTimeout });
|
||||
};
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import wallet from '../locators/wallet.locators';
|
||||
|
||||
const vegaWalletContainer = '[data-testid="vega-wallet"]';
|
||||
const restConnectorForm = '[data-testid="rest-connector-form"]';
|
||||
const vegaWalletName = Cypress.env('vegaWalletName');
|
||||
const vegaWalletLocation = Cypress.env('vegaWalletLocation');
|
||||
const vegaWalletPassphrase = Cypress.env('vegaWalletPassphrase');
|
||||
|
||||
cy.vega_wallet_import = () => {
|
||||
Cypress.Commands.add('vega_wallet_import', () => {
|
||||
cy.highlight(`Importing Vega Wallet ${vegaWalletName}`);
|
||||
cy.exec(`vegawallet init -f --home ${vegaWalletLocation}`);
|
||||
cy.exec(
|
||||
@ -14,11 +14,11 @@ cy.vega_wallet_import = () => {
|
||||
cy.exec(
|
||||
`vegawallet service run --network DV --automatic-consent --home ${vegaWalletLocation}`
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
cy.vega_wallet_connect = () => {
|
||||
Cypress.Commands.add('vega_wallet_connect', () => {
|
||||
cy.highlight('Connecting Vega Wallet');
|
||||
cy.get(wallet.vegawallet).within(() => {
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.get('button')
|
||||
.contains('Connect Vega wallet to use associated $VEGA')
|
||||
.should('be.enabled')
|
||||
@ -26,31 +26,31 @@ cy.vega_wallet_connect = () => {
|
||||
.click({ force: true });
|
||||
});
|
||||
cy.get('button').contains('rest provider').click();
|
||||
cy.get(wallet.connectRestForm).within(() => {
|
||||
cy.get(wallet.name).click().type(vegaWalletName);
|
||||
cy.get(wallet.passphrase).click().type(vegaWalletPassphrase);
|
||||
cy.get(restConnectorForm).within(() => {
|
||||
cy.get('#wallet').click().type(vegaWalletName);
|
||||
cy.get('#passphrase').click().type(vegaWalletPassphrase);
|
||||
cy.get('button').contains('Connect').click();
|
||||
});
|
||||
cy.contains(`${vegaWalletName} key`, { timeout: 20000 }).should('be.visible');
|
||||
};
|
||||
});
|
||||
|
||||
cy.vega_wallet_check_unstaked_value_is = (expectedVal) => {
|
||||
Cypress.Commands.add('vega_wallet_check_unstaked_value_is', (expectedVal) => {
|
||||
cy.highlight(`Checking vega wallet - Unstaked Value is ${expectedVal}`);
|
||||
cy.get(wallet.vegawallet).within(() => {
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.contains('Unstaked', { timeout: 40000 })
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
cy.vega_wallet_check_associated_value_is = (expectedVal) => {
|
||||
Cypress.Commands.add('vega_wallet_check_associated_value_is', (expectedVal) => {
|
||||
cy.highlight(`Checking vega wallet - Associated Value is ${expectedVal}`);
|
||||
cy.get(wallet.vegawallet).within(() => {
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.contains('Associated', { timeout: 40000 })
|
||||
.parent()
|
||||
.siblings()
|
||||
.contains(expectedVal, { timeout: 40000 })
|
||||
.should('be.visible');
|
||||
});
|
||||
};
|
||||
});
|
@ -128,7 +128,7 @@ const ConnectedKey = () => {
|
||||
return (
|
||||
<>
|
||||
{totalVestedBalance.plus(totalLockedBalance).isEqualTo(0) ? null : (
|
||||
<>
|
||||
<section data-testid="vega-in-vesting-contract">
|
||||
<WalletCardAsset
|
||||
image={vegaVesting}
|
||||
decimals={appState.decimals}
|
||||
@ -145,7 +145,7 @@ const ConnectedKey = () => {
|
||||
rightLabel={t('Unlocked')}
|
||||
light={false}
|
||||
/>
|
||||
</>
|
||||
</section>
|
||||
)}
|
||||
{!Object.keys(appState.associationBreakdown.vestingAssociations)
|
||||
.length ? null : (
|
||||
@ -154,22 +154,24 @@ const ConnectedKey = () => {
|
||||
notAssociated={notAssociatedInContract}
|
||||
/>
|
||||
)}
|
||||
<WalletCardAsset
|
||||
image={vegaWhite}
|
||||
decimals={appState.decimals}
|
||||
name="VEGA"
|
||||
symbol="In Wallet"
|
||||
balance={walletWithAssociations}
|
||||
dark={true}
|
||||
/>
|
||||
{!Object.keys(
|
||||
appState.associationBreakdown.stakingAssociations
|
||||
) ? null : (
|
||||
<AssociatedAmounts
|
||||
associations={appState.associationBreakdown.stakingAssociations}
|
||||
notAssociated={walletBalance}
|
||||
<section data-testid="vega-in-wallet">
|
||||
<WalletCardAsset
|
||||
image={vegaWhite}
|
||||
decimals={appState.decimals}
|
||||
name="VEGA"
|
||||
symbol="In Wallet"
|
||||
balance={walletWithAssociations}
|
||||
dark={true}
|
||||
/>
|
||||
)}
|
||||
{!Object.keys(
|
||||
appState.associationBreakdown.stakingAssociations
|
||||
) ? null : (
|
||||
<AssociatedAmounts
|
||||
associations={appState.associationBreakdown.stakingAssociations}
|
||||
notAssociated={walletBalance}
|
||||
/>
|
||||
)}
|
||||
</section>
|
||||
<WalletCardActions>
|
||||
<Link
|
||||
className={getButtonClasses('flex-1 mr-4', 'secondary')}
|
||||
@ -201,7 +203,12 @@ export const EthWallet = () => {
|
||||
<h1 className="text-h3 uppercase">{t('ethereumKey')}</h1>
|
||||
{account && (
|
||||
<div className="px-4 text-right">
|
||||
<div className="font-mono">{truncateMiddle(account)}</div>
|
||||
<div
|
||||
className="font-mono"
|
||||
data-testid="ethereum-account-truncated"
|
||||
>
|
||||
{truncateMiddle(account)}
|
||||
</div>
|
||||
{pendingTxs && (
|
||||
<div>
|
||||
<button
|
||||
@ -245,6 +252,7 @@ export const EthWallet = () => {
|
||||
<button
|
||||
className="mt-4 underline"
|
||||
onClick={() => connector.deactivate()}
|
||||
data-testid="disconnect-from-eth-wallet-button"
|
||||
>
|
||||
{t('disconnect')}
|
||||
</button>
|
||||
|
@ -99,6 +99,7 @@ export const LockedProgress = ({
|
||||
'border-black': light,
|
||||
'border-white': !light,
|
||||
})}
|
||||
data-testid="progress-bar"
|
||||
>
|
||||
<ProgressBar percentage={lockedPercentage} bgColor={leftColor} />
|
||||
<ProgressBar percentage={unlockedPercentage} bgColor={rightColor} />
|
||||
@ -119,8 +120,12 @@ export const LockedProgress = ({
|
||||
</ProgressContents>
|
||||
|
||||
<ProgressContents light={light}>
|
||||
<span>{formatNumber(locked, decimals)}</span>
|
||||
<span>{formatNumber(unlocked, decimals)}</span>
|
||||
<span data-testid="currency-locked">
|
||||
{formatNumber(locked, decimals)}
|
||||
</span>
|
||||
<span data-testid="currency-unlocked">
|
||||
{formatNumber(unlocked, decimals)}
|
||||
</span>
|
||||
</ProgressContents>
|
||||
</div>
|
||||
);
|
||||
|
@ -47,7 +47,10 @@ interface WalletCardHeaderProps {
|
||||
|
||||
export const WalletCardHeader = ({ children }: WalletCardHeaderProps) => {
|
||||
return (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-[auto_1fr] gap-4">
|
||||
<div
|
||||
className="grid grid-cols-1 sm:grid-cols-[auto_1fr] gap-4"
|
||||
data-testid="wallet-header"
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
@ -151,7 +154,10 @@ export const WalletCardAsset = ({
|
||||
}`}
|
||||
/>
|
||||
<div>
|
||||
<div className="flex font-medium align-center">
|
||||
<div
|
||||
className="flex font-medium align-center"
|
||||
data-testid="currency-title"
|
||||
>
|
||||
<h1
|
||||
className={`text-h5 mb-0 px-8 uppercase leading-none ${
|
||||
dark ? 'text-white' : 'text-black'
|
||||
@ -167,7 +173,10 @@ export const WalletCardAsset = ({
|
||||
{subheading || symbol}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="px-8 text-h5 basis-full font-mono">
|
||||
<div
|
||||
className="px-8 text-h5 basis-full font-mono"
|
||||
data-testid="currency-value"
|
||||
>
|
||||
<span>{integers}.</span>
|
||||
<span className={dark ? 'text-white-60' : 'text-black-60'}>
|
||||
{decimalsPlaces}
|
||||
|
@ -68,7 +68,7 @@ export const Web3Content = ({ children, appChainId }: Web3ContentProps) => {
|
||||
return (
|
||||
<Splash>
|
||||
<div className="flex flex-col items-center gap-12">
|
||||
<p>Something went wrong: {error.message}</p>
|
||||
<p className="text-white">Something went wrong: {error.message}</p>
|
||||
<Button onClick={() => connector.deactivate()}>Disconnect</Button>
|
||||
</div>
|
||||
</Splash>
|
||||
@ -79,7 +79,9 @@ export const Web3Content = ({ children, appChainId }: Web3ContentProps) => {
|
||||
return (
|
||||
<Splash>
|
||||
<div className="flex flex-col items-center gap-12">
|
||||
<p>This app only works on chain ID: {appChainId}</p>
|
||||
<p className="text-white">
|
||||
This app only works on chain ID: {appChainId}
|
||||
</p>
|
||||
<Button onClick={() => connector.deactivate()}>Disconnect</Button>
|
||||
</div>
|
||||
</Splash>
|
||||
|
@ -18,21 +18,25 @@ describe('accounts', () => {
|
||||
|
||||
cy.getByTestId('tab-accounts').should('be.visible');
|
||||
cy.getByTestId('tab-accounts')
|
||||
.should('be.visible')
|
||||
.get(`[row-id='General-tEURO-null']`)
|
||||
.find('[col-id="asset.symbol"]')
|
||||
.should('have.text', 'tEURO');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.should('be.visible')
|
||||
.get(`[row-id='General-tEURO-null']`)
|
||||
.find('[col-id="type"]')
|
||||
.should('have.text', 'General');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.should('be.visible')
|
||||
.get(`[row-id='General-tEURO-null']`)
|
||||
.find('[col-id="market.name"]')
|
||||
.should('have.text', '—');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.should('be.visible')
|
||||
.get(`[row-id='General-tEURO-null']`)
|
||||
.find('[col-id="balance"]')
|
||||
.should('have.text', '1,000.00000');
|
||||
|
@ -33,7 +33,7 @@ describe('deal ticket orders', () => {
|
||||
const orderTIFDropDown = 'order-tif';
|
||||
const placeOrderBtn = 'place-order';
|
||||
const orderStatusHeader = 'order-status-header';
|
||||
const orderTransactionHash = 'tx-hash';
|
||||
const orderTransactionHash = 'tx-block-explorer';
|
||||
|
||||
before(() => {
|
||||
cy.mockGQL((req) => {
|
||||
|
@ -19,6 +19,7 @@ describe('positions', () => {
|
||||
cy.getByTestId('tab-positions').should('be.visible');
|
||||
cy.getByTestId('tab-positions')
|
||||
.get('[col-id="market.tradableInstrument.instrument.code"]')
|
||||
.should('be.visible')
|
||||
.each(($marketSymbol) => {
|
||||
cy.wrap($marketSymbol).invoke('text').should('not.be.empty');
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { Orders, Orders_party_orders } from '@vegaprotocol/order-list';
|
||||
import type { Orders, Orders_party_orders } from '@vegaprotocol/orders';
|
||||
import {
|
||||
OrderStatus,
|
||||
OrderTimeInForce,
|
||||
|
@ -3,7 +3,7 @@
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { MarketTradingMode } from "@vegaprotocol/types";
|
||||
import { MarketTradingMode, MarketState } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: MarketsLanding
|
||||
@ -27,6 +27,10 @@ export interface MarketsLanding_markets {
|
||||
* Current mode of execution of the market
|
||||
*/
|
||||
tradingMode: MarketTradingMode;
|
||||
/**
|
||||
* Current state of the market
|
||||
*/
|
||||
state: MarketState;
|
||||
/**
|
||||
* timestamps for state changes in the market
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect } from 'react';
|
||||
import { useGlobalStore } from '../stores';
|
||||
@ -12,6 +12,7 @@ const MARKETS_QUERY = gql`
|
||||
markets {
|
||||
id
|
||||
tradingMode
|
||||
state
|
||||
marketTimestamps {
|
||||
open
|
||||
}
|
||||
@ -20,13 +21,13 @@ const MARKETS_QUERY = gql`
|
||||
`;
|
||||
|
||||
const marketList = ({ markets }: MarketsLanding) =>
|
||||
sortBy(
|
||||
orderBy(
|
||||
markets?.filter(
|
||||
({ marketTimestamps, tradingMode }) =>
|
||||
marketTimestamps.open && tradingMode === MarketTradingMode.Continuous
|
||||
) || [],
|
||||
'marketTimestamps.open',
|
||||
'id'
|
||||
['state', 'marketTimestamps.open', 'id'],
|
||||
['asc', 'asc', 'asc']
|
||||
);
|
||||
|
||||
export function Index() {
|
||||
|
@ -81,6 +81,7 @@ const MarketPage = ({ id }: { id?: string }) => {
|
||||
return (
|
||||
<PageQueryContainer<Market, MarketVariables>
|
||||
query={MARKET_QUERY}
|
||||
data-testid="market"
|
||||
options={{
|
||||
variables: {
|
||||
marketId,
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
DealTicketContainer,
|
||||
MarketInfoContainer,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import { OrderListContainer } from '@vegaprotocol/order-list';
|
||||
import { OrderListContainer } from '@vegaprotocol/orders';
|
||||
import { TradesContainer } from '@vegaprotocol/trades';
|
||||
import { PositionsContainer } from '@vegaprotocol/positions';
|
||||
import { OrderbookContainer } from '@vegaprotocol/market-depth';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Web3Container } from '../../components/web3-container';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { PositionsContainer } from '@vegaprotocol/positions';
|
||||
import { OrderListContainer } from '@vegaprotocol/order-list';
|
||||
import { OrderListContainer } from '@vegaprotocol/orders';
|
||||
import { AccountsContainer } from '@vegaprotocol/accounts';
|
||||
import { AnchorButton, Tab, Tabs } from '@vegaprotocol/ui-toolkit';
|
||||
import { WithdrawalsContainer } from './withdrawals/withdrawals-container';
|
||||
|
67
libs/deal-ticket/src/components/__generated__/MarketNames.ts
generated
Normal file
67
libs/deal-ticket/src/components/__generated__/MarketNames.ts
generated
Normal file
@ -0,0 +1,67 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: MarketNames
|
||||
// ====================================================
|
||||
|
||||
export interface MarketNames_markets_tradableInstrument_instrument_metadata {
|
||||
__typename: "InstrumentMetadata";
|
||||
/**
|
||||
* An arbitrary list of tags to associated to associate to the Instrument (string list)
|
||||
*/
|
||||
tags: string[] | null;
|
||||
}
|
||||
|
||||
export interface MarketNames_markets_tradableInstrument_instrument_product {
|
||||
__typename: "Future";
|
||||
/**
|
||||
* String representing the quote (e.g. BTCUSD -> USD is quote)
|
||||
*/
|
||||
quoteName: string;
|
||||
}
|
||||
|
||||
export interface MarketNames_markets_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Metadata for this instrument
|
||||
*/
|
||||
metadata: MarketNames_markets_tradableInstrument_instrument_metadata;
|
||||
/**
|
||||
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
|
||||
*/
|
||||
product: MarketNames_markets_tradableInstrument_instrument_product;
|
||||
}
|
||||
|
||||
export interface MarketNames_markets_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of or reference to a fully specified instrument.
|
||||
*/
|
||||
instrument: MarketNames_markets_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface MarketNames_markets {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Market full name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* An instance of or reference to a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: MarketNames_markets_tradableInstrument;
|
||||
}
|
||||
|
||||
export interface MarketNames {
|
||||
/**
|
||||
* One or more instruments that are trading on the VEGA network
|
||||
*/
|
||||
markets: MarketNames_markets[] | null;
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
export * from './DealTicketQuery';
|
||||
export * from './MarketInfoQuery';
|
||||
export * from './MarketNames';
|
||||
|
@ -1,11 +1,11 @@
|
||||
import type { UseFormRegister } from 'react-hook-form';
|
||||
import { OrderType } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '../utils/get-default-order';
|
||||
import { VegaWalletOrderType } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import { DealTicketMarketAmount } from './deal-ticket-market-amount';
|
||||
import { DealTicketLimitAmount } from './deal-ticket-limit-amount';
|
||||
|
||||
export interface DealTicketAmountProps {
|
||||
orderType: OrderType;
|
||||
orderType: VegaWalletOrderType;
|
||||
step: number;
|
||||
register: UseFormRegister<Order>;
|
||||
quoteName: string;
|
||||
@ -17,9 +17,9 @@ export const DealTicketAmount = ({
|
||||
...props
|
||||
}: DealTicketAmountProps) => {
|
||||
switch (orderType) {
|
||||
case OrderType.Market:
|
||||
case VegaWalletOrderType.Market:
|
||||
return <DealTicketMarketAmount {...props} />;
|
||||
case OrderType.Limit:
|
||||
case VegaWalletOrderType.Limit:
|
||||
return <DealTicketLimitAmount {...props} />;
|
||||
default: {
|
||||
throw new Error('Invalid ticket type');
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { FormGroup, Input } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { validateSize } from '../utils/validate-size';
|
||||
import { validateSize } from '@vegaprotocol/orders';
|
||||
import type { DealTicketAmountProps } from './deal-ticket-amount';
|
||||
|
||||
export type DealTicketLimitAmountProps = Omit<
|
||||
|
@ -1,11 +1,10 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import { OrderStatus } from '@vegaprotocol/types';
|
||||
import { VegaOrderTransactionDialog, VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
import { useState } from 'react';
|
||||
import { VegaTransactionDialog, VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
import { DealTicket } from './deal-ticket';
|
||||
import { useOrderSubmit } from '../hooks/use-order-submit';
|
||||
import type { DealTicketQuery_market } from './__generated__/DealTicketQuery';
|
||||
import { useOrderSubmit } from '@vegaprotocol/orders';
|
||||
import { OrderStatus } from '@vegaprotocol/types';
|
||||
|
||||
export interface DealTicketManagerProps {
|
||||
market: DealTicketQuery_market;
|
||||
@ -18,43 +17,20 @@ export const DealTicketManager = ({
|
||||
}: DealTicketManagerProps) => {
|
||||
const [orderDialogOpen, setOrderDialogOpen] = useState(false);
|
||||
const { submit, transaction, finalizedOrder, reset } = useOrderSubmit(market);
|
||||
|
||||
const getDialogIntent = (status: VegaTxStatus) => {
|
||||
if (finalizedOrder) {
|
||||
if (
|
||||
finalizedOrder.status === OrderStatus.Active ||
|
||||
finalizedOrder.status === OrderStatus.Filled ||
|
||||
finalizedOrder.status === OrderStatus.PartiallyFilled
|
||||
) {
|
||||
return Intent.Success;
|
||||
}
|
||||
|
||||
if (finalizedOrder.status === OrderStatus.Parked) {
|
||||
return Intent.Warning;
|
||||
}
|
||||
|
||||
return Intent.Danger;
|
||||
const getDialogTitle = (status?: string) => {
|
||||
switch (status) {
|
||||
case OrderStatus.Active:
|
||||
return 'Order submitted';
|
||||
case OrderStatus.Filled:
|
||||
return 'Order filled';
|
||||
case OrderStatus.PartiallyFilled:
|
||||
return 'Order partially filled';
|
||||
case OrderStatus.Parked:
|
||||
return 'Order parked';
|
||||
default:
|
||||
return 'Submission failed';
|
||||
}
|
||||
|
||||
if (status === VegaTxStatus.Requested) {
|
||||
return Intent.Warning;
|
||||
}
|
||||
|
||||
if (status === VegaTxStatus.Error) {
|
||||
return Intent.Danger;
|
||||
}
|
||||
|
||||
return Intent.None;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (transaction.status !== VegaTxStatus.Default || finalizedOrder) {
|
||||
setOrderDialogOpen(true);
|
||||
} else {
|
||||
setOrderDialogOpen(false);
|
||||
}
|
||||
}, [finalizedOrder, transaction.status]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{children || (
|
||||
@ -69,23 +45,15 @@ export const DealTicketManager = ({
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<Dialog
|
||||
open={orderDialogOpen}
|
||||
onChange={(isOpen) => {
|
||||
setOrderDialogOpen(isOpen);
|
||||
|
||||
// If closing reset
|
||||
if (!isOpen) {
|
||||
reset();
|
||||
}
|
||||
}}
|
||||
intent={getDialogIntent(transaction.status)}
|
||||
>
|
||||
<VegaOrderTransactionDialog
|
||||
transaction={transaction}
|
||||
finalizedOrder={finalizedOrder}
|
||||
/>
|
||||
</Dialog>
|
||||
<VegaTransactionDialog
|
||||
key={`submit-order-dialog-${transaction.txHash}`}
|
||||
orderDialogOpen={orderDialogOpen}
|
||||
setOrderDialogOpen={setOrderDialogOpen}
|
||||
finalizedOrder={finalizedOrder}
|
||||
transaction={transaction}
|
||||
reset={reset}
|
||||
title={getDialogTitle(finalizedOrder?.status)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { FormGroup, Input } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { validateSize } from '../utils/validate-size';
|
||||
import { validateSize } from '@vegaprotocol/orders';
|
||||
import type { DealTicketAmountProps } from './deal-ticket-amount';
|
||||
|
||||
export type DealTicketMarketAmountProps = Omit<
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {
|
||||
VegaWalletContext,
|
||||
OrderTimeInForce,
|
||||
OrderType,
|
||||
VegaWalletOrderTimeInForce,
|
||||
VegaWalletOrderType,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { addDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { fireEvent, render, screen, act } from '@testing-library/react';
|
||||
@ -64,7 +64,7 @@ it('Displays ticket defaults', () => {
|
||||
|
||||
// Assert defaults are used
|
||||
expect(
|
||||
screen.getByTestId(`order-type-${OrderType.Market}-selected`)
|
||||
screen.getByTestId(`order-type-${VegaWalletOrderType.Market}-selected`)
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByTestId('order-side-SIDE_BUY-selected')
|
||||
@ -75,7 +75,9 @@ it('Displays ticket defaults', () => {
|
||||
expect(screen.getByTestId('order-size')).toHaveDisplayValue(
|
||||
String(1 / Math.pow(10, market.positionDecimalPlaces))
|
||||
);
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.IOC);
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(
|
||||
VegaWalletOrderTimeInForce.IOC
|
||||
);
|
||||
|
||||
// Assert last price is shown
|
||||
expect(screen.getByTestId('last-price')).toHaveTextContent(
|
||||
@ -101,9 +103,11 @@ it('Can edit deal ticket', async () => {
|
||||
expect(screen.getByTestId('order-size')).toHaveDisplayValue('200');
|
||||
|
||||
fireEvent.change(screen.getByTestId('order-tif'), {
|
||||
target: { value: OrderTimeInForce.IOC },
|
||||
target: { value: VegaWalletOrderTimeInForce.IOC },
|
||||
});
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.IOC);
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(
|
||||
VegaWalletOrderTimeInForce.IOC
|
||||
);
|
||||
|
||||
// Switch to limit order
|
||||
fireEvent.click(screen.getByTestId('order-type-TYPE_LIMIT'));
|
||||
@ -113,7 +117,7 @@ it('Can edit deal ticket', async () => {
|
||||
|
||||
// Check all TIF options shown
|
||||
expect(screen.getByTestId('order-tif').children).toHaveLength(
|
||||
Object.keys(OrderTimeInForce).length
|
||||
Object.keys(VegaWalletOrderTimeInForce).length
|
||||
);
|
||||
});
|
||||
|
||||
@ -130,26 +134,34 @@ it('Handles TIF select box dependent on order type', () => {
|
||||
// Switch to limit order and check all TIF options shown
|
||||
fireEvent.click(screen.getByTestId('order-type-TYPE_LIMIT'));
|
||||
expect(screen.getByTestId('order-tif').children).toHaveLength(
|
||||
Object.keys(OrderTimeInForce).length
|
||||
Object.keys(VegaWalletOrderTimeInForce).length
|
||||
);
|
||||
|
||||
// Change to GTC
|
||||
fireEvent.change(screen.getByTestId('order-tif'), {
|
||||
target: { value: OrderTimeInForce.GTC },
|
||||
target: { value: VegaWalletOrderTimeInForce.GTC },
|
||||
});
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.GTC);
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(
|
||||
VegaWalletOrderTimeInForce.GTC
|
||||
);
|
||||
|
||||
// Switch back to market order and TIF should now be IOC
|
||||
fireEvent.click(screen.getByTestId('order-type-TYPE_MARKET'));
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.IOC);
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(
|
||||
VegaWalletOrderTimeInForce.IOC
|
||||
);
|
||||
|
||||
// Switch tif to FOK
|
||||
fireEvent.change(screen.getByTestId('order-tif'), {
|
||||
target: { value: OrderTimeInForce.FOK },
|
||||
target: { value: VegaWalletOrderTimeInForce.FOK },
|
||||
});
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.FOK);
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(
|
||||
VegaWalletOrderTimeInForce.FOK
|
||||
);
|
||||
|
||||
// Change back to limit and check we are still on FOK
|
||||
fireEvent.click(screen.getByTestId('order-type-TYPE_LIMIT'));
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.FOK);
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(
|
||||
VegaWalletOrderTimeInForce.FOK
|
||||
);
|
||||
});
|
||||
|
@ -1,17 +1,19 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { OrderType, OrderTimeInForce } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
VegaWalletOrderType,
|
||||
VegaWalletOrderTimeInForce,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { t, addDecimal, toDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { Button, InputError } from '@vegaprotocol/ui-toolkit';
|
||||
import { TypeSelector } from './type-selector';
|
||||
import { SideSelector } from './side-selector';
|
||||
import { DealTicketAmount } from './deal-ticket-amount';
|
||||
import { TimeInForceSelector } from './time-in-force-selector';
|
||||
import { useOrderValidation } from '../hooks/use-order-validation';
|
||||
import type { DealTicketQuery_market } from './__generated__/DealTicketQuery';
|
||||
import type { Order } from '../utils/get-default-order';
|
||||
import { getDefaultOrder } from '../utils/get-default-order';
|
||||
import { ExpirySelector } from './expiry-selector';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import { getDefaultOrder, useOrderValidation } from '@vegaprotocol/orders';
|
||||
|
||||
export type TransactionStatus = 'default' | 'pending';
|
||||
|
||||
@ -97,8 +99,8 @@ export const DealTicket = ({
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{orderType === OrderType.Limit &&
|
||||
orderTimeInForce === OrderTimeInForce.GTT && (
|
||||
{orderType === VegaWalletOrderType.Limit &&
|
||||
orderTimeInForce === VegaWalletOrderTimeInForce.GTT && (
|
||||
<Controller
|
||||
name="expiration"
|
||||
control={control}
|
||||
|
@ -10,3 +10,4 @@ export * from './info-market';
|
||||
export * from './side-selector';
|
||||
export * from './time-in-force-selector';
|
||||
export * from './type-selector';
|
||||
export * from './market-selector';
|
||||
|
292
libs/deal-ticket/src/components/market-selector.tsx
Normal file
292
libs/deal-ticket/src/components/market-selector.tsx
Normal file
@ -0,0 +1,292 @@
|
||||
import React, {
|
||||
useCallback,
|
||||
useState,
|
||||
useEffect,
|
||||
useRef,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import classNames from 'classnames';
|
||||
import type { DealTicketQuery_market } from './__generated__';
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
Icon,
|
||||
Input,
|
||||
Loader,
|
||||
Splash,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
t,
|
||||
useScreenDimensions,
|
||||
useOutsideClick,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
MarketNames,
|
||||
MarketNames_markets,
|
||||
} from './__generated__/MarketNames';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
|
||||
export const MARKET_NAMES_QUERY = gql`
|
||||
query MarketNames {
|
||||
markets {
|
||||
id
|
||||
name
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
metadata {
|
||||
tags
|
||||
}
|
||||
product {
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
market: DealTicketQuery_market;
|
||||
setMarket: (marketId: string) => void;
|
||||
ItemRenderer?: React.FC<{ market: MarketNames_markets }>;
|
||||
}
|
||||
|
||||
function escapeRegExp(str: string) {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
|
||||
const { isMobile } = useScreenDimensions();
|
||||
const contRef = useRef<HTMLDivElement | null>(null);
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
const arrowButtonRef = useRef<HTMLButtonElement | null>(null);
|
||||
const [skip, setSkip] = useState(true);
|
||||
const [results, setResults] = useState<MarketNames_markets[]>([]);
|
||||
const [showPane, setShowPane] = useState(false);
|
||||
const [lookup, setLookup] = useState(market.name || '');
|
||||
const [dialogContent, setDialogContent] = useState<React.ReactNode | null>(
|
||||
null
|
||||
);
|
||||
|
||||
const { data, loading, error } = useQuery<MarketNames>(MARKET_NAMES_QUERY, {
|
||||
skip,
|
||||
});
|
||||
|
||||
const outsideClickCb = useCallback(() => {
|
||||
if (!isMobile) {
|
||||
setShowPane(false);
|
||||
}
|
||||
}, [setShowPane, isMobile]);
|
||||
|
||||
useOutsideClick({ refs: [contRef, arrowButtonRef], func: outsideClickCb });
|
||||
|
||||
const handleOnChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const {
|
||||
target: { value },
|
||||
} = event;
|
||||
setLookup(value);
|
||||
setShowPane(true);
|
||||
if (value) {
|
||||
setSkip(false);
|
||||
}
|
||||
},
|
||||
[setLookup, setShowPane, setSkip]
|
||||
);
|
||||
|
||||
const handleMarketSelect = useCallback(
|
||||
({ id, name }) => {
|
||||
setLookup(name);
|
||||
setShowPane(false);
|
||||
setMarket(id);
|
||||
inputRef.current?.focus();
|
||||
},
|
||||
[setLookup, setShowPane, setMarket, inputRef]
|
||||
);
|
||||
|
||||
const handleItemKeyDown = useCallback(
|
||||
(
|
||||
event: React.KeyboardEvent,
|
||||
market: MarketNames_markets,
|
||||
index: number
|
||||
) => {
|
||||
switch (event.key) {
|
||||
case 'ArrowDown':
|
||||
if (index < results.length - 1) {
|
||||
(contRef.current?.children[index + 1] as HTMLDivElement).focus();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ArrowUp':
|
||||
if (!index) {
|
||||
inputRef.current?.focus();
|
||||
inputRef.current?.setSelectionRange(
|
||||
inputRef.current?.value.length,
|
||||
inputRef.current?.value.length
|
||||
);
|
||||
return;
|
||||
}
|
||||
(contRef.current?.children[index - 1] as HTMLDivElement).focus();
|
||||
break;
|
||||
|
||||
case 'Enter':
|
||||
handleMarketSelect(market);
|
||||
break;
|
||||
}
|
||||
},
|
||||
[results, handleMarketSelect]
|
||||
);
|
||||
|
||||
const handleInputKeyDown = useCallback(
|
||||
(event: React.KeyboardEvent) => {
|
||||
if (event.key === 'ArrowDown') {
|
||||
(contRef.current?.children[0] as HTMLDivElement).focus();
|
||||
}
|
||||
},
|
||||
[contRef]
|
||||
);
|
||||
|
||||
const handleOnBlur = useCallback(() => {
|
||||
console.log('lookup, showPane', lookup, showPane);
|
||||
if (!lookup && !showPane) {
|
||||
console.log(
|
||||
'2 lookup, showPane, market.name',
|
||||
lookup,
|
||||
showPane,
|
||||
market.name
|
||||
);
|
||||
setLookup(market.name);
|
||||
}
|
||||
}, [market, lookup, showPane, setLookup]);
|
||||
|
||||
const openPane = useCallback(() => {
|
||||
setShowPane(!showPane);
|
||||
setSkip(false);
|
||||
inputRef.current?.focus();
|
||||
}, [showPane, setShowPane, setSkip, inputRef]);
|
||||
|
||||
const handleDialogOnchange = useCallback(
|
||||
(isOpen) => {
|
||||
setShowPane(isOpen);
|
||||
if (!isOpen) {
|
||||
setLookup(lookup || market.name);
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
},
|
||||
[setShowPane, lookup, setLookup, market.name, inputRef]
|
||||
);
|
||||
|
||||
const selectorContent = useMemo(() => {
|
||||
return (
|
||||
<div className="relative flex flex-col">
|
||||
<div className="relative w-full min-h-[30px] dark:bg-black">
|
||||
<Input
|
||||
className="h-[30px] w-[calc(100%-20px)] border-none dark:bg-black"
|
||||
ref={inputRef}
|
||||
tabIndex={0}
|
||||
value={lookup}
|
||||
placeholder={t('Search')}
|
||||
onChange={handleOnChange}
|
||||
onKeyDown={handleInputKeyDown}
|
||||
onBlur={handleOnBlur}
|
||||
/>
|
||||
<Button
|
||||
className="absolute self-end top-[7px] right-0 z-10"
|
||||
variant="inline-link"
|
||||
onClick={openPane}
|
||||
ref={arrowButtonRef}
|
||||
data-testid="arrow-button"
|
||||
>
|
||||
<Icon
|
||||
name={IconNames.ARROW_DOWN}
|
||||
className={classNames('fill-current transition-transform', {
|
||||
'rotate-180': showPane,
|
||||
})}
|
||||
size={16}
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
<hr className="md:hidden mb-5" />
|
||||
<div
|
||||
className={classNames(
|
||||
'md:absolute 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',
|
||||
showPane ? 'block' : 'hidden'
|
||||
)}
|
||||
data-testid="market-pane"
|
||||
>
|
||||
{loading && <Loader />}
|
||||
{error && (
|
||||
<Splash>{t(`Something went wrong: ${error.message}`)}</Splash>
|
||||
)}
|
||||
<div ref={contRef} className="w-full">
|
||||
{results.map((market, i) => (
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
key={market.id}
|
||||
className="cursor-pointer focus:bg-white-95 focus:outline-0 dark:focus:bg-black-80 px-20 py-5"
|
||||
onClick={() => handleMarketSelect(market)}
|
||||
onKeyDown={(e) => handleItemKeyDown(e, market, i)}
|
||||
>
|
||||
{ItemRenderer ? <ItemRenderer market={market} /> : market.name}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}, [
|
||||
ItemRenderer,
|
||||
error,
|
||||
handleInputKeyDown,
|
||||
handleItemKeyDown,
|
||||
handleMarketSelect,
|
||||
handleOnBlur,
|
||||
handleOnChange,
|
||||
loading,
|
||||
lookup,
|
||||
openPane,
|
||||
results,
|
||||
showPane,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
setResults(
|
||||
data?.markets?.filter((item: MarketNames_markets) =>
|
||||
item.name.match(new RegExp(escapeRegExp(lookup), 'i'))
|
||||
) || []
|
||||
);
|
||||
}, [data, lookup]);
|
||||
|
||||
useEffect(() => {
|
||||
inputRef.current?.focus();
|
||||
}, [inputRef]);
|
||||
|
||||
useEffect(() => {
|
||||
if (showPane && isMobile) {
|
||||
setDialogContent(selectorContent);
|
||||
inputRef.current?.focus();
|
||||
window.scrollTo(0, 0);
|
||||
} else {
|
||||
setDialogContent(null);
|
||||
}
|
||||
}, [selectorContent, showPane, isMobile, setDialogContent]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{!dialogContent && selectorContent}
|
||||
<Dialog
|
||||
titleClassNames="uppercase font-alpha"
|
||||
contentClassNames="left-[0px] top-[99px] h-[calc(100%-99px)] border-0 translate-x-[0] translate-y-[0] border-none overflow-y-auto"
|
||||
title={t('Select Market')}
|
||||
open={Boolean(dialogContent)}
|
||||
onChange={handleDialogOnchange}
|
||||
>
|
||||
{dialogContent}
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,16 +1,16 @@
|
||||
import { FormGroup } from '@vegaprotocol/ui-toolkit';
|
||||
import { OrderSide } from '@vegaprotocol/wallet';
|
||||
import { VegaWalletOrderSide } from '@vegaprotocol/wallet';
|
||||
import { Toggle } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
|
||||
interface SideSelectorProps {
|
||||
value: OrderSide;
|
||||
onSelect: (side: OrderSide) => void;
|
||||
value: VegaWalletOrderSide;
|
||||
onSelect: (side: VegaWalletOrderSide) => void;
|
||||
}
|
||||
|
||||
export const SideSelector = ({ value, onSelect }: SideSelectorProps) => {
|
||||
const toggles = Object.entries(OrderSide).map(([label, value]) => ({
|
||||
label,
|
||||
const toggles = Object.entries(VegaWalletOrderSide).map(([label, value]) => ({
|
||||
label: label === 'Buy' ? 'Long' : 'Short',
|
||||
value,
|
||||
}));
|
||||
|
||||
@ -21,7 +21,7 @@ export const SideSelector = ({ value, onSelect }: SideSelectorProps) => {
|
||||
name="order-side"
|
||||
toggles={toggles}
|
||||
checkedValue={value}
|
||||
onChange={(e) => onSelect(e.target.value as OrderSide)}
|
||||
onChange={(e) => onSelect(e.target.value as VegaWalletOrderSide)}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { FormGroup, Select } from '@vegaprotocol/ui-toolkit';
|
||||
import { OrderTimeInForce, OrderType } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
VegaWalletOrderTimeInForce,
|
||||
VegaWalletOrderType,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
|
||||
interface TimeInForceSelectorProps {
|
||||
value: OrderTimeInForce;
|
||||
orderType: OrderType;
|
||||
onSelect: (tif: OrderTimeInForce) => void;
|
||||
value: VegaWalletOrderTimeInForce;
|
||||
orderType: VegaWalletOrderType;
|
||||
onSelect: (tif: VegaWalletOrderTimeInForce) => void;
|
||||
}
|
||||
|
||||
export const TimeInForceSelector = ({
|
||||
@ -14,12 +17,12 @@ export const TimeInForceSelector = ({
|
||||
onSelect,
|
||||
}: TimeInForceSelectorProps) => {
|
||||
const options =
|
||||
orderType === OrderType.Limit
|
||||
? Object.entries(OrderTimeInForce)
|
||||
: Object.entries(OrderTimeInForce).filter(
|
||||
orderType === VegaWalletOrderType.Limit
|
||||
? Object.entries(VegaWalletOrderTimeInForce)
|
||||
: Object.entries(VegaWalletOrderTimeInForce).filter(
|
||||
([_, timeInForce]) =>
|
||||
timeInForce === OrderTimeInForce.FOK ||
|
||||
timeInForce === OrderTimeInForce.IOC
|
||||
timeInForce === VegaWalletOrderTimeInForce.FOK ||
|
||||
timeInForce === VegaWalletOrderTimeInForce.IOC
|
||||
);
|
||||
|
||||
return (
|
||||
@ -27,7 +30,7 @@ export const TimeInForceSelector = ({
|
||||
<Select
|
||||
id="select-time-in-force"
|
||||
value={value}
|
||||
onChange={(e) => onSelect(e.target.value as OrderTimeInForce)}
|
||||
onChange={(e) => onSelect(e.target.value as VegaWalletOrderTimeInForce)}
|
||||
className="w-full"
|
||||
data-testid="order-tif"
|
||||
>
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { FormGroup } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { OrderType } from '@vegaprotocol/wallet';
|
||||
import { VegaWalletOrderType } from '@vegaprotocol/wallet';
|
||||
import { Toggle } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
interface TypeSelectorProps {
|
||||
value: OrderType;
|
||||
onSelect: (type: OrderType) => void;
|
||||
value: VegaWalletOrderType;
|
||||
onSelect: (type: VegaWalletOrderType) => void;
|
||||
}
|
||||
|
||||
const toggles = Object.entries(OrderType).map(([label, value]) => ({
|
||||
const toggles = Object.entries(VegaWalletOrderType).map(([label, value]) => ({
|
||||
label,
|
||||
value,
|
||||
}));
|
||||
@ -21,7 +21,7 @@ export const TypeSelector = ({ value, onSelect }: TypeSelectorProps) => {
|
||||
name="order-type"
|
||||
toggles={toggles}
|
||||
checkedValue={value}
|
||||
onChange={(e) => onSelect(e.target.value as OrderType)}
|
||||
onChange={(e) => onSelect(e.target.value as VegaWalletOrderType)}
|
||||
/>
|
||||
</FormGroup>
|
||||
);
|
||||
|
114
libs/deal-ticket/src/hooks/__generated__/OrderEvent.ts
generated
114
libs/deal-ticket/src/hooks/__generated__/OrderEvent.ts
generated
@ -1,114 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { BusEventType, OrderType, OrderStatus, OrderRejectionReason } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL subscription operation: OrderEvent
|
||||
// ====================================================
|
||||
|
||||
export interface OrderEvent_busEvents_event_TimeUpdate {
|
||||
__typename: "TimeUpdate" | "MarketEvent" | "TransferResponses" | "PositionResolution" | "Trade" | "Account" | "Party" | "MarginLevels" | "Proposal" | "Vote" | "MarketData" | "NodeSignature" | "LossSocialization" | "SettlePosition" | "Market" | "Asset" | "MarketTick" | "SettleDistressed" | "AuctionEvent" | "RiskFactor" | "Deposit" | "Withdrawal" | "OracleSpec" | "LiquidityProvision";
|
||||
}
|
||||
|
||||
export interface OrderEvent_busEvents_event_Order_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market full name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
|
||||
* number denominated in the currency of the Market. (uint64)
|
||||
*
|
||||
* Examples:
|
||||
* Currency Balance decimalPlaces Real Balance
|
||||
* GBP 100 0 GBP 100
|
||||
* GBP 100 2 GBP 1.00
|
||||
* GBP 100 4 GBP 0.01
|
||||
* GBP 1 4 GBP 0.0001 ( 0.01p )
|
||||
*
|
||||
* GBX (pence) 100 0 GBP 1.00 (100p )
|
||||
* GBX (pence) 100 2 GBP 0.01 ( 1p )
|
||||
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
|
||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||
*/
|
||||
decimalPlaces: number;
|
||||
/**
|
||||
* positionDecimalPlaces indicated the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||
*/
|
||||
positionDecimalPlaces: number;
|
||||
}
|
||||
|
||||
export interface OrderEvent_busEvents_event_Order {
|
||||
__typename: "Order";
|
||||
/**
|
||||
* Type the order type (defaults to PARTY)
|
||||
*/
|
||||
type: OrderType | null;
|
||||
/**
|
||||
* Hash of the order data
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The status of an order, for example 'Active'
|
||||
*/
|
||||
status: OrderStatus;
|
||||
/**
|
||||
* Reason for the order to be rejected
|
||||
*/
|
||||
rejectionReason: OrderRejectionReason | null;
|
||||
/**
|
||||
* RFC3339Nano formatted date and time for when the order was created (timestamp)
|
||||
*/
|
||||
createdAt: string;
|
||||
/**
|
||||
* Total number of contracts that may be bought or sold (immutable) (uint64)
|
||||
*/
|
||||
size: string;
|
||||
/**
|
||||
* The worst price the order will trade at (e.g. buy for price or less, sell for price or more) (uint64)
|
||||
*/
|
||||
price: string;
|
||||
/**
|
||||
* The market the order is trading on (probably stored internally as a hash of the market details)
|
||||
*/
|
||||
market: OrderEvent_busEvents_event_Order_market | null;
|
||||
}
|
||||
|
||||
export type OrderEvent_busEvents_event = OrderEvent_busEvents_event_TimeUpdate | OrderEvent_busEvents_event_Order;
|
||||
|
||||
export interface OrderEvent_busEvents {
|
||||
__typename: "BusEvent";
|
||||
/**
|
||||
* the id for this event
|
||||
*/
|
||||
eventId: string;
|
||||
/**
|
||||
* the block hash
|
||||
*/
|
||||
block: string;
|
||||
/**
|
||||
* the type of event we're dealing with
|
||||
*/
|
||||
type: BusEventType;
|
||||
/**
|
||||
* the payload - the wrapped event
|
||||
*/
|
||||
event: OrderEvent_busEvents_event;
|
||||
}
|
||||
|
||||
export interface OrderEvent {
|
||||
/**
|
||||
* Subscribe to event data from the event bus
|
||||
*/
|
||||
busEvents: OrderEvent_busEvents[] | null;
|
||||
}
|
||||
|
||||
export interface OrderEventVariables {
|
||||
partyId: string;
|
||||
}
|
@ -1,176 +0,0 @@
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { act, renderHook } from '@testing-library/react-hooks';
|
||||
import type { Order } from '../utils/get-default-order';
|
||||
import type {
|
||||
VegaKeyExtended,
|
||||
VegaWalletContextShape,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { VegaTxStatus, VegaWalletContext } from '@vegaprotocol/wallet';
|
||||
import { OrderSide, OrderTimeInForce, OrderType } from '@vegaprotocol/wallet';
|
||||
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useOrderSubmit } from './use-order-submit';
|
||||
import type { DealTicketQuery_market } from '../components/__generated__/DealTicketQuery';
|
||||
|
||||
const defaultMarket: DealTicketQuery_market = {
|
||||
__typename: 'Market',
|
||||
id: 'market-id',
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 1,
|
||||
tradingMode: MarketTradingMode.Continuous,
|
||||
state: MarketState.Active,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'quote-name',
|
||||
},
|
||||
},
|
||||
},
|
||||
depth: {
|
||||
__typename: 'MarketDepth',
|
||||
lastTrade: {
|
||||
__typename: 'Trade',
|
||||
price: '100',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const defaultWalletContext = {
|
||||
keypair: null,
|
||||
keypairs: [],
|
||||
sendTx: jest.fn().mockReturnValue(Promise.resolve(null)),
|
||||
connect: jest.fn(),
|
||||
disconnect: jest.fn(),
|
||||
selectPublicKey: jest.fn(),
|
||||
connector: null,
|
||||
};
|
||||
|
||||
function setup(
|
||||
context?: Partial<VegaWalletContextShape>,
|
||||
market = defaultMarket
|
||||
) {
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<MockedProvider>
|
||||
<VegaWalletContext.Provider
|
||||
value={{ ...defaultWalletContext, ...context }}
|
||||
>
|
||||
{children}
|
||||
</VegaWalletContext.Provider>
|
||||
</MockedProvider>
|
||||
);
|
||||
return renderHook(() => useOrderSubmit(market), { wrapper });
|
||||
}
|
||||
|
||||
it('Has the correct default state', () => {
|
||||
const { result } = setup();
|
||||
expect(typeof result.current.submit).toEqual('function');
|
||||
expect(typeof result.current.reset).toEqual('function');
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Default);
|
||||
expect(result.current.transaction.txHash).toEqual(null);
|
||||
expect(result.current.transaction.error).toEqual(null);
|
||||
});
|
||||
|
||||
it('Should not sendTx if no keypair', async () => {
|
||||
const mockSendTx = jest.fn();
|
||||
const { result } = setup({ sendTx: mockSendTx, keypairs: [], keypair: null });
|
||||
await act(async () => {
|
||||
result.current.submit({} as Order);
|
||||
});
|
||||
expect(mockSendTx).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Should not sendTx side is not specified', async () => {
|
||||
const mockSendTx = jest.fn();
|
||||
const keypair = {
|
||||
pub: '0x123',
|
||||
} as VegaKeyExtended;
|
||||
const { result } = setup({
|
||||
sendTx: mockSendTx,
|
||||
keypairs: [keypair],
|
||||
keypair,
|
||||
});
|
||||
await act(async () => {
|
||||
result.current.submit({} as Order);
|
||||
});
|
||||
expect(mockSendTx).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Create an Id if a signature is returned', async () => {
|
||||
const signature =
|
||||
'597a7706491e6523c091bab1e4d655b62c45a224e80f6cd92ac366aa5dd9a070cc7dd3c6919cb07b81334b876c662dd43bdbe5e827c8baa17a089feb654fab0b';
|
||||
const expectedId =
|
||||
'2fe09b0e2e6ed35f8883802629c7d609d3cc2fc9ce3cec0b7824a0d581bd3747';
|
||||
const successObj = {
|
||||
tx: {
|
||||
inputData: 'input-data',
|
||||
signature: {
|
||||
algo: 'algo',
|
||||
version: 1,
|
||||
value: signature,
|
||||
},
|
||||
},
|
||||
txHash: '0x123',
|
||||
};
|
||||
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve(successObj));
|
||||
const keypair = {
|
||||
pub: '0x123',
|
||||
} as VegaKeyExtended;
|
||||
const { result } = setup({
|
||||
sendTx: mockSendTx,
|
||||
keypairs: [keypair],
|
||||
keypair,
|
||||
});
|
||||
await act(async () => {
|
||||
result.current.submit({
|
||||
type: OrderType.Market,
|
||||
side: OrderSide.Buy,
|
||||
size: '1',
|
||||
timeInForce: OrderTimeInForce.FOK,
|
||||
});
|
||||
});
|
||||
expect(result.current.id).toEqual(expectedId);
|
||||
});
|
||||
|
||||
it('Should submit a correctly formatted order', async () => {
|
||||
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve({}));
|
||||
const keypair = {
|
||||
pub: '0x123',
|
||||
} as VegaKeyExtended;
|
||||
const { result } = setup(
|
||||
{
|
||||
sendTx: mockSendTx,
|
||||
keypairs: [keypair],
|
||||
keypair,
|
||||
},
|
||||
defaultMarket
|
||||
);
|
||||
|
||||
const order: Order = {
|
||||
type: OrderType.Limit,
|
||||
size: '10',
|
||||
timeInForce: OrderTimeInForce.GTT,
|
||||
side: OrderSide.Buy,
|
||||
price: '1234567.89',
|
||||
expiration: new Date('2022-01-01'),
|
||||
};
|
||||
await act(async () => {
|
||||
result.current.submit(order);
|
||||
});
|
||||
|
||||
expect(mockSendTx).toHaveBeenCalledWith({
|
||||
pubKey: keypair.pub,
|
||||
propagate: true,
|
||||
orderSubmission: {
|
||||
type: OrderType.Limit,
|
||||
marketId: defaultMarket.id, // Market provided from hook arugment
|
||||
size: '100', // size adjusted based on positionDecimalPlaces
|
||||
side: OrderSide.Buy,
|
||||
timeInForce: OrderTimeInForce.GTT,
|
||||
price: '123456789', // Decimal removed
|
||||
expiresAt: order.expiration?.getTime() + '000000', // Nanoseconds appened
|
||||
},
|
||||
});
|
||||
});
|
@ -1,102 +0,0 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useSubscription } from '@apollo/client';
|
||||
import type { Order } from '../utils/get-default-order';
|
||||
import type {
|
||||
OrderEvent,
|
||||
OrderEventVariables,
|
||||
OrderEvent_busEvents_event_Order,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import {
|
||||
OrderType,
|
||||
useVegaWallet,
|
||||
ORDER_EVENT_SUB,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { determineId, removeDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { useVegaTransaction } from '@vegaprotocol/wallet';
|
||||
import type { DealTicketQuery_market } from '../components/__generated__/DealTicketQuery';
|
||||
|
||||
export const useOrderSubmit = (market: DealTicketQuery_market) => {
|
||||
const { keypair } = useVegaWallet();
|
||||
const { send, transaction, reset: resetTransaction } = useVegaTransaction();
|
||||
const [id, setId] = useState('');
|
||||
const [finalizedOrder, setFinalizedOrder] =
|
||||
useState<OrderEvent_busEvents_event_Order | null>(null);
|
||||
|
||||
// Start a subscription looking for the newly created order
|
||||
useSubscription<OrderEvent, OrderEventVariables>(ORDER_EVENT_SUB, {
|
||||
variables: { partyId: keypair?.pub || '' },
|
||||
skip: !id,
|
||||
onSubscriptionData: ({ subscriptionData }) => {
|
||||
if (!subscriptionData.data?.busEvents?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No types available for the subscription result
|
||||
const matchingOrderEvent = subscriptionData.data.busEvents.find((e) => {
|
||||
if (e.event.__typename !== 'Order') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return e.event.id === id;
|
||||
});
|
||||
|
||||
if (
|
||||
matchingOrderEvent &&
|
||||
matchingOrderEvent.event.__typename === 'Order'
|
||||
) {
|
||||
setFinalizedOrder(matchingOrderEvent.event);
|
||||
resetTransaction();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const submit = useCallback(
|
||||
async (order: Order) => {
|
||||
if (!keypair || !order.side) {
|
||||
return;
|
||||
}
|
||||
|
||||
setFinalizedOrder(null);
|
||||
|
||||
const res = await send({
|
||||
pubKey: keypair.pub,
|
||||
propagate: true,
|
||||
orderSubmission: {
|
||||
marketId: market.id,
|
||||
price:
|
||||
order.type === OrderType.Limit && order.price
|
||||
? removeDecimal(order.price, market.decimalPlaces)
|
||||
: undefined,
|
||||
size: removeDecimal(order.size, market.positionDecimalPlaces),
|
||||
type: order.type,
|
||||
side: order.side,
|
||||
timeInForce: order.timeInForce,
|
||||
expiresAt: order.expiration
|
||||
? // Wallet expects timestamp in nanoseconds, we don't have that level of accuracy so
|
||||
// just append 6 zeroes
|
||||
order.expiration.getTime().toString() + '000000'
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
if (res?.signature) {
|
||||
setId(determineId(res.signature));
|
||||
}
|
||||
},
|
||||
[market, keypair, send]
|
||||
);
|
||||
|
||||
const reset = useCallback(() => {
|
||||
resetTransaction();
|
||||
setFinalizedOrder(null);
|
||||
setId('');
|
||||
}, [resetTransaction]);
|
||||
|
||||
return {
|
||||
transaction,
|
||||
finalizedOrder,
|
||||
id,
|
||||
submit,
|
||||
reset,
|
||||
};
|
||||
};
|
@ -1,4 +1 @@
|
||||
export * from './components';
|
||||
export * from './utils/get-default-order';
|
||||
export * from './hooks/use-order-submit';
|
||||
export * from './hooks/use-order-validation';
|
||||
|
@ -1,28 +0,0 @@
|
||||
import { OrderTimeInForce, OrderType, OrderSide } from '@vegaprotocol/wallet';
|
||||
import { toDecimal } from '@vegaprotocol/react-helpers';
|
||||
import type { DealTicketQuery_market } from '../components/__generated__/DealTicketQuery';
|
||||
|
||||
export type Order =
|
||||
| {
|
||||
size: string;
|
||||
type: OrderType.Market;
|
||||
timeInForce: OrderTimeInForce;
|
||||
side: OrderSide;
|
||||
price?: never;
|
||||
expiration?: never;
|
||||
}
|
||||
| {
|
||||
size: string;
|
||||
type: OrderType.Limit;
|
||||
timeInForce: OrderTimeInForce;
|
||||
side: OrderSide;
|
||||
price?: string;
|
||||
expiration?: Date;
|
||||
};
|
||||
|
||||
export const getDefaultOrder = (market: DealTicketQuery_market): Order => ({
|
||||
type: OrderType.Market,
|
||||
side: OrderSide.Buy,
|
||||
timeInForce: OrderTimeInForce.IOC,
|
||||
size: String(toDecimal(market.positionDecimalPlaces)),
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user