test(governance): governance tests refactor (#3059)

This commit is contained in:
Joe Tsang 2023-03-22 17:35:00 +00:00 committed by GitHub
parent 6c1c5bf2a9
commit 8d8f6b4928
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 2721 additions and 2694 deletions

View File

@ -1,9 +1,28 @@
import { associateTokenStartOfTests } from '../../support/common.functions';
import { import {
navigateTo,
waitForSpinner,
navigation,
} from '../../support/common.functions';
import {
convertUnixTimestampToDateformat,
createRawProposal, createRawProposal,
createTenDigitUnixTimeStampForSpecifiedDays,
enterUniqueFreeFormProposalBody,
generateFreeFormProposalTitle, generateFreeFormProposalTitle,
getGovernanceProposalDateFormatForSpecifiedDays,
getProposalIdFromList,
getProposalInformationFromTable,
getSubmittedProposalFromProposalList,
goToMakeNewProposal,
governanceProposalType, governanceProposalType,
} from '../../support/governance.functions'; voteForProposal,
waitForProposalSubmitted,
waitForProposalSync,
} from '../../../../governance-e2e/src/support/governance.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../../../governance-e2e/src/support/staking.functions';
import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../../../governance-e2e/src/support/wallet-teardown.functions';
import type { testFreeformProposal } from '../../support/common-interfaces';
const proposalVoteProgressForPercentage = const proposalVoteProgressForPercentage =
'[data-testid="vote-progress-indicator-percentage-for"]'; '[data-testid="vote-progress-indicator-percentage-for"]';
@ -25,24 +44,23 @@ describe(
function () { function () {
before('connect wallets and set approval limit', function () { before('connect wallets and set approval limit', function () {
cy.visit('/'); cy.visit('/');
cy.vega_wallet_set_specified_approval_amount('1000'); vegaWalletSetSpecifiedApprovalAmount('1000');
associateTokenStartOfTests();
}); });
beforeEach('visit proposals tab', function () { beforeEach('visit proposals tab', function () {
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.ethereum_wallet_connect(); ethereumWalletConnect();
cy.ensure_specified_unstaked_tokens_are_associated(1); ensureSpecifiedUnstakedTokensAreAssociated('1');
cy.navigate_to_page_if_not_already_loaded('proposals'); navigateTo(navigation.proposals);
}); });
// 3001-VOTE-055 // 3001-VOTE-055
it('Newly created raw proposal details - shows proposal title and full description', function () { it('Newly created raw proposal details - shows proposal title and full description', function () {
createRawProposal(); createRawProposal();
cy.get('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
cy.get_proposal_id_from_list(rawProposal.rationale.title); getProposalIdFromList(rawProposal.rationale.title);
cy.get('@proposalIdText').then((proposalId) => { cy.get('@proposalIdText').then((proposalId) => {
cy.get(openProposals).within(() => { cy.get(openProposals).within(() => {
cy.get(`#${proposalId}`).within(() => { cy.get(`#${proposalId}`).within(() => {
@ -69,30 +87,26 @@ describe(
it('Newly created freeform proposal details - shows proposed and closing dates', function () { it('Newly created freeform proposal details - shows proposed and closing dates', function () {
const closingVoteHrs = '72'; const closingVoteHrs = '72';
const proposalTitle = generateFreeFormProposalTitle(); const proposalTitle = generateFreeFormProposalTitle();
const proposalTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM); goToMakeNewProposal(governanceProposalType.FREEFORM);
cy.create_ten_digit_unix_timestamp_for_specified_days('3').then( enterUniqueFreeFormProposalBody(closingVoteHrs, proposalTitle);
(closingDateTimestamp) => { waitForProposalSubmitted();
cy.enter_unique_freeform_proposal_body(closingVoteHrs, proposalTitle); waitForProposalSync();
navigateTo(navigation.proposals);
cy.wait_for_proposal_submitted(); getSubmittedProposalFromProposalList(proposalTitle).within(() =>
cy.wait_for_proposal_sync(); cy.get(viewProposalButton).click()
cy.navigate_to('proposals'); );
cy.get_submitted_proposal_from_proposal_list(proposalTitle).within( convertUnixTimestampToDateformat(proposalTimeStamp).then(
() => cy.get(viewProposalButton).click() (closingDate) => {
); getProposalInformationFromTable('Closes on')
cy.convert_unix_timestamp_to_governance_data_table_date_format( .contains(closingDate)
closingDateTimestamp .should('be.visible');
).then((closingDate) => {
cy.get_proposal_information_from_table('Closes on')
.contains(closingDate)
.should('be.visible');
});
} }
); );
cy.get_governance_proposal_date_format_for_specified_days('0').then( getGovernanceProposalDateFormatForSpecifiedDays(0).then(
(proposalDate) => { (proposalDate) => {
cy.get_proposal_information_from_table('Proposed on') getProposalInformationFromTable('Proposed on')
.contains(proposalDate) .contains(proposalDate)
.should('be.visible'); .should('be.visible');
} }
@ -104,25 +118,25 @@ describe(
// 3001-VOTE-040 // 3001-VOTE-040
// 3001-VOTE-067 // 3001-VOTE-067
createRawProposal(); createRawProposal();
cy.get('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
cy.get_submitted_proposal_from_proposal_list( getSubmittedProposalFromProposalList(
rawProposal.rationale.title rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click()); ).within(() => cy.get(viewProposalButton).click());
}); });
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should( cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
'be.visible' 'be.visible'
); );
cy.get_proposal_information_from_table('Expected to pass') getProposalInformationFromTable('Expected to pass')
.contains('👎') .contains('👎')
.should('be.visible'); .should('be.visible');
// 3001-VOTE-062 // 3001-VOTE-062
// 3001-VOTE-040 // 3001-VOTE-040
// 3001-VOTE-070 // 3001-VOTE-070
cy.get_proposal_information_from_table('Token majority met') getProposalInformationFromTable('Token majority met')
.contains('👎') .contains('👎')
.should('be.visible'); .should('be.visible');
// 3001-VOTE-068 // 3001-VOTE-068
cy.get_proposal_information_from_table('Token participation met') getProposalInformationFromTable('Token participation met')
.contains('👎') .contains('👎')
.should('be.visible'); .should('be.visible');
}); });
@ -130,28 +144,27 @@ describe(
// 3001-VOTE-080 3001-VOTE-090 3001-VOTE-069 3001-VOTE-072 3001-VOTE-073 // 3001-VOTE-080 3001-VOTE-090 3001-VOTE-069 3001-VOTE-072 3001-VOTE-073
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () { it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
createRawProposal(); createRawProposal();
cy.get('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
cy.get_submitted_proposal_from_proposal_list( getSubmittedProposalFromProposalList(
rawProposal.rationale.title rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click()); ).within(() => cy.get(viewProposalButton).click());
}); });
// 3001-VOTE-080 // 3001-VOTE-080
cy.getByTestId('vote-buttons').contains('against').should('be.visible'); cy.getByTestId('vote-buttons').contains('against').should('be.visible');
cy.getByTestId('vote-buttons').contains('for').should('be.visible'); cy.getByTestId('vote-buttons').contains('for').should('be.visible');
cy.vote_for_proposal('for'); voteForProposal('for');
cy.get_governance_proposal_date_format_for_specified_days( getGovernanceProposalDateFormatForSpecifiedDays(0, 'shortMonth').then(
'0', (votedDate) => {
'shortMonth' // 3001-VOTE-051
).then((votedDate) => { // 3001-VOTE-093
// 3001-VOTE-051 cy.contains('You voted:')
// 3001-VOTE-093 .siblings()
cy.contains('You voted:') .contains('For')
.siblings() .siblings()
.contains('For') .contains(votedDate)
.siblings() .should('be.visible');
.contains(votedDate) }
.should('be.visible'); );
});
cy.get(proposalVoteProgressForPercentage) // 3001-VOTE-072 cy.get(proposalVoteProgressForPercentage) // 3001-VOTE-072
.contains('100.00%') .contains('100.00%')
.and('be.visible'); .and('be.visible');
@ -162,38 +175,38 @@ describe(
cy.get(proposalVoteProgressAgainstTokens) cy.get(proposalVoteProgressAgainstTokens)
.contains('0.00') .contains('0.00')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Tokens for proposal') getProposalInformationFromTable('Tokens for proposal')
.should('have.text', parseFloat(1).toFixed(2)) .should('have.text', (1).toFixed(2))
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Tokens against proposal') getProposalInformationFromTable('Tokens against proposal')
.should('have.text', '0.00') .should('have.text', '0.00')
.and('be.visible'); .and('be.visible');
// 3001-VOTE-061 // 3001-VOTE-061
cy.get_proposal_information_from_table('Participation required') getProposalInformationFromTable('Participation required')
.contains(0.001) .contains('0.00%')
.should('be.visible'); .should('be.visible');
// 3001-VOTE-066 // 3001-VOTE-066
cy.get_proposal_information_from_table('Majority Required') // 3001-VOTE-073 getProposalInformationFromTable('Majority Required') // 3001-VOTE-073
.contains(`${parseFloat(100).toFixed(2)}%`) .contains(`${(66).toFixed(2)}%`)
.should('be.visible'); .should('be.visible');
cy.get_proposal_information_from_table('Number of voting parties') getProposalInformationFromTable('Number of voting parties')
.should('have.text', '1') .should('have.text', '1')
.and('be.visible'); .and('be.visible');
cy.get(changeVoteButton).should('be.visible').click(); cy.get(changeVoteButton).should('be.visible').click();
cy.vote_for_proposal('for'); voteForProposal('for');
// 3001-VOTE-064 // 3001-VOTE-064
cy.get_proposal_information_from_table('Tokens for proposal') getProposalInformationFromTable('Tokens for proposal')
.should('have.text', parseFloat(1).toFixed(2)) .should('have.text', (1).toFixed(2))
.and('be.visible'); .and('be.visible');
cy.get(changeVoteButton).should('be.visible').click(); cy.get(changeVoteButton).should('be.visible').click();
cy.vote_for_proposal('against'); voteForProposal('against');
cy.get(proposalVoteProgressAgainstPercentage) cy.get(proposalVoteProgressAgainstPercentage)
.contains('100.00%') .contains('100.00%')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Tokens against proposal') getProposalInformationFromTable('Tokens against proposal')
.should('have.text', parseFloat(1).toFixed(2)) .should('have.text', (1).toFixed(2))
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Number of voting parties') getProposalInformationFromTable('Number of voting parties')
.should('have.text', '1') .should('have.text', '1')
.and('be.visible'); .and('be.visible');
}); });
@ -201,30 +214,31 @@ describe(
// 3001-VOTE-042, 3001-VOTE-057, 3001-VOTE-058, 3001-VOTE-059, 3001-VOTE-060 // 3001-VOTE-042, 3001-VOTE-057, 3001-VOTE-058, 3001-VOTE-059, 3001-VOTE-060
it('Newly created proposal details - ability to increase associated tokens - by voting again after association', function () { it('Newly created proposal details - ability to increase associated tokens - by voting again after association', function () {
createRawProposal(); createRawProposal();
cy.get('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
cy.get_submitted_proposal_from_proposal_list( getSubmittedProposalFromProposalList(rawProposal.rationale.title)
rawProposal.rationale.title
)
.as('submittedProposal') .as('submittedProposal')
.within(() => cy.get(viewProposalButton).click()); .within(() => cy.get(viewProposalButton).click());
}); });
cy.vote_for_proposal('for'); voteForProposal('for');
// 3001-VOTE-079 // 3001-VOTE-079
cy.contains('You voted: For').should('be.visible'); cy.contains('You voted: For').should('be.visible');
cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible'); cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible');
cy.get_proposal_information_from_table('Total Supply') getProposalInformationFromTable('Total Supply')
.invoke('text') .invoke('text')
.then((totalSupply) => { .then((totalSupply) => {
let tokensRequiredToAchieveResult = parseFloat( const tokensRequiredToAchieveResult = (
(totalSupply.replace(/,/g, '') * 0.001) / 100 (Number(totalSupply.replace(/,/g, '')) * 0.001) /
100
).toFixed(2); ).toFixed(2);
cy.ensure_specified_unstaked_tokens_are_associated( ensureSpecifiedUnstakedTokensAreAssociated(
tokensRequiredToAchieveResult tokensRequiredToAchieveResult
); );
cy.navigate_to_page_if_not_already_loaded('proposals'); navigateTo(navigation.proposals);
cy.get('@submittedProposal').within(() => cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
cy.get(viewProposalButton).click() getSubmittedProposalFromProposalList(rawProposal.rationale.title)
); .as('submittedProposal')
.within(() => cy.get(viewProposalButton).click());
});
cy.get(proposalVoteProgressForPercentage) cy.get(proposalVoteProgressForPercentage)
.contains('100.00%') .contains('100.00%')
.and('be.visible'); .and('be.visible');
@ -233,38 +247,36 @@ describe(
.and('be.visible'); .and('be.visible');
// 3001-VOTE-065 // 3001-VOTE-065
cy.get(changeVoteButton).should('be.visible').click(); cy.get(changeVoteButton).should('be.visible').click();
cy.vote_for_proposal('for'); voteForProposal('for');
cy.get(proposalVoteProgressForTokens) cy.get(proposalVoteProgressForTokens)
.contains(tokensRequiredToAchieveResult) .contains(tokensRequiredToAchieveResult)
.and('be.visible'); .and('be.visible');
cy.get(proposalVoteProgressAgainstTokens) cy.get(proposalVoteProgressAgainstTokens)
.contains('0.00') .contains('0.00')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table( getProposalInformationFromTable('Total tokens voted percentage')
'Total tokens voted percentage'
)
.should('have.text', '0.00%') .should('have.text', '0.00%')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Tokens for proposal') getProposalInformationFromTable('Tokens for proposal')
.should('have.text', tokensRequiredToAchieveResult) .should('have.text', tokensRequiredToAchieveResult)
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Tokens against proposal') getProposalInformationFromTable('Tokens against proposal')
.should('have.text', '0.00') .should('have.text', '0.00')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Number of voting parties') getProposalInformationFromTable('Number of voting parties')
.should('have.text', '1') .should('have.text', '1')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Expected to pass') getProposalInformationFromTable('Expected to pass')
.contains('👍') .contains('👍')
.should('be.visible'); .should('be.visible');
// 3001-VOTE-062 // 3001-VOTE-062
cy.get_proposal_information_from_table('Token majority met') getProposalInformationFromTable('Token majority met')
.contains('👍') .contains('👍')
.should('be.visible'); .should('be.visible');
cy.get_proposal_information_from_table('Token participation met') getProposalInformationFromTable('Token participation met')
.contains('👍') .contains('👍')
.should('be.visible'); .should('be.visible');
cy.get_proposal_information_from_table('Tokens for proposal') getProposalInformationFromTable('Tokens for proposal')
.contains(tokensRequiredToAchieveResult) .contains(tokensRequiredToAchieveResult)
.and('be.visible'); .and('be.visible');
}); });

View File

@ -1,10 +1,21 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
import { associateTokenStartOfTests } from '../../support/governance.functions'; import {
navigateTo,
navigation,
waitForSpinner,
} from '../../support/common.functions';
import {
getProposalInformationFromTable,
voteForProposal,
} from '../../support/governance.functions';
import { import {
createUpdateNetworkProposalTxBody, createUpdateNetworkProposalTxBody,
createFreeFormProposalTxBody, createFreeFormProposalTxBody,
} from '../../support/proposal.functions'; } from '../../support/proposal.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
const closedProposals = '[data-testid="closed-proposals"]'; const closedProposals = '[data-testid="closed-proposals"]';
const proposalStatus = '[data-testid="proposal-status"]'; const proposalStatus = '[data-testid="proposal-status"]';
@ -21,20 +32,19 @@ context(
function () { function () {
before('Connect wallets and set approval', function () { before('Connect wallets and set approval', function () {
cy.visit('/'); cy.visit('/');
cy.vega_wallet_set_specified_approval_amount('1000'); vegaWalletSetSpecifiedApprovalAmount('1000');
associateTokenStartOfTests();
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.ethereum_wallet_connect(); ethereumWalletConnect();
cy.ensure_specified_unstaked_tokens_are_associated(1); ensureSpecifiedUnstakedTokensAreAssociated('1');
cy.clearLocalStorage(); cy.clearLocalStorage();
}); });
beforeEach('visit proposals', function () { beforeEach('visit proposals', function () {
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.ethereum_wallet_connect(); ethereumWalletConnect();
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
}); });
// 3001-VOTE-006 // 3001-VOTE-006
@ -43,7 +53,7 @@ context(
cy.createMarket(); cy.createMarket();
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.get(closedProposals).within(() => { cy.get(closedProposals).within(() => {
cy.contains(proposalTitle) cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]') .parentsUntil('[data-testid="proposals-list-item"]')
@ -53,7 +63,7 @@ context(
}); });
}); });
cy.getByTestId('proposal-type').should('have.text', 'New market'); cy.getByTestId('proposal-type').should('have.text', 'New market');
cy.get_proposal_information_from_table('State') getProposalInformationFromTable('State')
.contains('Enacted') .contains('Enacted')
.and('be.visible'); .and('be.visible');
cy.get(votesTable).within(() => { cy.get(votesTable).within(() => {
@ -68,22 +78,22 @@ context(
const proposalTx = createUpdateNetworkProposalTxBody(); const proposalTx = createUpdateNetworkProposalTxBody();
cy.VegaWalletSubmitProposal(proposalTx); cy.VegaWalletSubmitProposal(proposalTx);
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.get(openProposals).within(() => { cy.get(openProposals).within(() => {
cy.contains(proposalTitle) cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]') .parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click()); .within(() => cy.get(viewProposalButton).click());
}); });
cy.get_proposal_information_from_table('State') getProposalInformationFromTable('State')
.contains('Open') .contains('Open')
.and('be.visible'); .and('be.visible');
cy.vote_for_proposal('for'); voteForProposal('for');
cy.get_proposal_information_from_table('State') // 3001-VOTE-047 getProposalInformationFromTable('State') // 3001-VOTE-047
.contains('Passed', proposalTimeout) .contains('Passed', proposalTimeout)
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('State') getProposalInformationFromTable('State')
.contains('Enacted', proposalTimeout) .contains('Enacted', proposalTimeout)
.and('be.visible'); .and('be.visible');
cy.get(votesTable).within(() => { cy.get(votesTable).within(() => {
@ -101,19 +111,19 @@ context(
const proposalTx = createFreeFormProposalTxBody(); const proposalTx = createFreeFormProposalTxBody();
cy.VegaWalletSubmitProposal(proposalTx); cy.VegaWalletSubmitProposal(proposalTx);
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.get(openProposals).within(() => { cy.get(openProposals).within(() => {
cy.contains(proposalTitle) cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]') .parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click()); .within(() => cy.get(viewProposalButton).click());
}); });
cy.get_proposal_information_from_table('State') getProposalInformationFromTable('State')
.contains('Open') .contains('Open')
.and('be.visible'); .and('be.visible');
cy.vote_for_proposal('for'); voteForProposal('for');
cy.get_proposal_information_from_table('State') getProposalInformationFromTable('State')
.contains('Enacted', proposalTimeout) .contains('Enacted', proposalTimeout)
.and('be.visible'); .and('be.visible');
}); });
@ -123,21 +133,21 @@ context(
const proposalTitle = 'Add New free form proposal with short enactment'; const proposalTitle = 'Add New free form proposal with short enactment';
const proposalTx = createFreeFormProposalTxBody(); const proposalTx = createFreeFormProposalTxBody();
cy.VegaWalletSubmitProposal(proposalTx); cy.VegaWalletSubmitProposal(proposalTx);
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.get(openProposals).within(() => { cy.get(openProposals).within(() => {
cy.contains(proposalTitle) cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]') .parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click()); .within(() => cy.get(viewProposalButton).click());
}); });
cy.get_proposal_information_from_table('State') getProposalInformationFromTable('State')
.contains('Open') .contains('Open')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('State') // 3001-VOTE-047 getProposalInformationFromTable('State') // 3001-VOTE-047
.contains('Declined', proposalTimeout) .contains('Declined', proposalTimeout)
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Rejection reason') getProposalInformationFromTable('Rejection reason')
.contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED') .contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED')
.and('be.visible'); .and('be.visible');
}); });

View File

@ -1,17 +1,42 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
import { import {
createRawProposal, createRawProposal,
createTenDigitUnixTimeStampForSpecifiedDays,
enterRawProposalBody,
enterUniqueFreeFormProposalBody,
generateFreeFormProposalTitle, generateFreeFormProposalTitle,
getProposalInformationFromTable,
getSubmittedProposalFromProposalList,
goToMakeNewProposal,
governanceProposalType, governanceProposalType,
voteForProposal,
waitForProposalSubmitted,
waitForProposalSync,
} from '../../support/governance.functions'; } from '../../support/governance.functions';
import { associateTokenStartOfTests } from '../../support/common.functions'; import {
verifyUnstakedBalance,
waitForSpinner,
navigateTo,
navigation,
} from '../../support/common.functions';
import {
clickOnValidatorFromList,
closeStakingDialog,
ensureSpecifiedUnstakedTokensAreAssociated,
stakingPageDisassociateTokens,
stakingValidatorPageAddStake,
} from '../../support/staking.functions';
import {
vegaWalletSetSpecifiedApprovalAmount,
vegaWalletTeardown,
} from '../../support/wallet-teardown.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import type { testFreeformProposal } from '../../support/common-interfaces';
const vegaWalletUnstakedBalance =
'[data-testid="vega-wallet-balance-unstaked"]';
const vegaWalletStakedBalances = const vegaWalletStakedBalances =
'[data-testid="vega-wallet-balance-staked-validators"]'; '[data-testid="vega-wallet-balance-staked-validators"]';
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]'; const vegaWalletAssociatedBalance = '[data-testid="associated-amount"]';
const vegaWalletNameElement = '[data-testid="wallet-name"]'; const vegaWalletNameElement = '[data-testid="wallet-name"]';
const vegaWallet = '[data-testid="vega-wallet"]'; const vegaWallet = '[data-testid="vega-wallet"]';
const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]'; const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]';
@ -40,30 +65,31 @@ context(
cy.visit('/'); cy.visit('/');
cy.get_network_parameters().then((network_parameters) => { cy.get_network_parameters().then((network_parameters) => {
cy.wrap( cy.wrap(
network_parameters['spam.protection.proposal.min.tokens'] / Number(network_parameters['spam.protection.proposal.min.tokens']) /
1000000000000000000 1000000000000000000
).as('minProposerBalance'); ).as('minProposerBalance');
cy.wrap( cy.wrap(
network_parameters['spam.protection.voting.min.tokens'] / Number(network_parameters['spam.protection.voting.min.tokens']) /
1000000000000000000 1000000000000000000
).as('minVoterBalance'); ).as('minVoterBalance');
cy.wrap( cy.wrap(
network_parameters['governance.proposal.freeform.requiredMajority'] * Number(
100 network_parameters['governance.proposal.freeform.requiredMajority']
) * 100
).as('requiredMajority'); ).as('requiredMajority');
}); });
cy.vega_wallet_set_specified_approval_amount('1000'); vegaWalletSetSpecifiedApprovalAmount('1000');
associateTokenStartOfTests(); cy.associateTokensToVegaWallet('1');
}); });
beforeEach('visit governance tab', function () { beforeEach('visit governance tab', function () {
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.ethereum_wallet_connect(); ethereumWalletConnect();
cy.ensure_specified_unstaked_tokens_are_associated(1); ensureSpecifiedUnstakedTokensAreAssociated('1');
cy.navigate_to_page_if_not_already_loaded('proposals'); navigateTo(navigation.proposals);
}); });
it('Should be able to see that no proposals exist', function () { it('Should be able to see that no proposals exist', function () {
@ -80,7 +106,7 @@ context(
// 3002-PROP-003 // 3002-PROP-003
it('Submit a proposal form - shows how many vega tokens are required to make a proposal', function () { it('Submit a proposal form - shows how many vega tokens are required to make a proposal', function () {
// 3002-PROP-005 // 3002-PROP-005
cy.go_to_make_new_proposal(governanceProposalType.NEW_MARKET); goToMakeNewProposal(governanceProposalType.NEW_MARKET);
cy.contains( cy.contains(
`You must have at least 1 VEGA associated to make a proposal` `You must have at least 1 VEGA associated to make a proposal`
).should('be.visible'); ).should('be.visible');
@ -88,7 +114,7 @@ context(
// 3002-PROP-011 // 3002-PROP-011
it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () { it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM); goToMakeNewProposal(governanceProposalType.FREEFORM);
cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008 cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008
cy.get(maxVoteButton).should('be.visible'); cy.get(maxVoteButton).should('be.visible');
cy.get(votingDate).should('not.be.empty'); cy.get(votingDate).should('not.be.empty');
@ -96,40 +122,31 @@ context(
'contain.text', 'contain.text',
'we add 2 minutes of extra time' 'we add 2 minutes of extra time'
); );
cy.enter_unique_freeform_proposal_body( enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle());
'50',
generateFreeFormProposalTitle()
);
// 3002-PROP-012 // 3002-PROP-012
// 3002-PROP-016 // 3002-PROP-016
cy.wait_for_proposal_submitted(); waitForProposalSubmitted();
}); });
it('Able to submit a valid freeform proposal - with minimum required tokens associated - but also staked', function () { it('Able to submit a valid freeform proposal - with minimum required tokens associated - but also staked', function () {
cy.ensure_specified_unstaked_tokens_are_associated('2'); ensureSpecifiedUnstakedTokensAreAssociated('2');
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', '2'); verifyUnstakedBalance(2);
cy.navigate_to('validators'); navigateTo(navigation.validators);
cy.click_on_validator_from_list(0); clickOnValidatorFromList(0);
cy.staking_validator_page_add_stake('2'); stakingValidatorPageAddStake('2');
cy.close_staking_dialog(); closeStakingDialog();
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2'); cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM); goToMakeNewProposal(governanceProposalType.FREEFORM);
cy.enter_unique_freeform_proposal_body( enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle());
'50', waitForProposalSubmitted();
generateFreeFormProposalTitle()
);
cy.wait_for_proposal_submitted();
}); });
it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () { it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM); goToMakeNewProposal(governanceProposalType.FREEFORM);
cy.enter_unique_freeform_proposal_body( enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle());
'0.1',
generateFreeFormProposalTitle()
);
cy.contains('Awaiting network confirmation', epochTimeout).should( cy.contains('Awaiting network confirmation', epochTimeout).should(
'not.exist' 'not.exist'
); );
@ -139,8 +156,8 @@ context(
}); });
it('Creating a proposal - proposal rejected - when closing time later than system default', function () { it('Creating a proposal - proposal rejected - when closing time later than system default', function () {
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM); goToMakeNewProposal(governanceProposalType.FREEFORM);
cy.enter_unique_freeform_proposal_body( enterUniqueFreeFormProposalBody(
'100000', '100000',
generateFreeFormProposalTitle() generateFreeFormProposalTitle()
); );
@ -154,22 +171,18 @@ context(
// 3001-VOTE-006 // 3001-VOTE-006
it('Creating a proposal - proposal rejected - able to access rejected proposals', function () { it('Creating a proposal - proposal rejected - able to access rejected proposals', function () {
cy.go_to_make_new_proposal(governanceProposalType.RAW); goToMakeNewProposal(governanceProposalType.RAW);
cy.create_ten_digit_unix_timestamp_for_specified_days('1000').then( enterRawProposalBody(createTenDigitUnixTimeStampForSpecifiedDays(1000));
(closingDateTimestamp) => {
cy.enter_raw_proposal_body(closingDateTimestamp).as('rawProposal');
}
);
cy.contains('Awaiting network confirmation', epochTimeout).should( cy.contains('Awaiting network confirmation', epochTimeout).should(
'be.visible' 'be.visible'
); );
cy.contains('Proposal rejected', proposalTimeout).should('be.visible'); cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
cy.get(dialogCloseButton).click(); cy.get(dialogCloseButton).click();
cy.wait_for_proposal_sync(); waitForProposalSync();
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
cy.get(rejectProposalsLink).click(); cy.get(rejectProposalsLink).click();
cy.get('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
cy.get_submitted_proposal_from_proposal_list( getSubmittedProposalFromProposalList(
rawProposal.rationale.title rawProposal.rationale.title
).within(() => { ).within(() => {
cy.contains('Rejected').should('be.visible'); cy.contains('Rejected').should('be.visible');
@ -177,78 +190,67 @@ context(
cy.get(viewProposalButton).click(); cy.get(viewProposalButton).click();
}); });
}); });
cy.get_proposal_information_from_table('State') getProposalInformationFromTable('State')
.contains('Rejected') .contains('Rejected')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Rejection reason') getProposalInformationFromTable('Rejection reason')
.contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE') .contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Error details') getProposalInformationFromTable('Error details')
.contains('proposal closing time too late') .contains('proposal closing time too late')
.and('be.visible'); .and('be.visible');
}); });
// 0005-ETXN-004 // 0005-ETXN-004
it('Unable to create a proposal - when no tokens are associated', function () { it('Unable to create a proposal - when no tokens are associated', function () {
cy.vega_wallet_teardown(); const errorMsg =
'Network error: the network blocked the transaction through the spam protection: party has insufficient associated governance tokens in their staking account to submit proposal request (ABCI code 89)';
vegaWalletTeardown();
cy.get(vegaWalletAssociatedBalance, txTimeout).contains( cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
'0.00', '0.00',
txTimeout txTimeout
); );
cy.go_to_make_new_proposal(governanceProposalType.RAW); goToMakeNewProposal(governanceProposalType.RAW);
cy.create_ten_digit_unix_timestamp_for_specified_days('8').then( enterRawProposalBody(createTenDigitUnixTimeStampForSpecifiedDays(8));
(closingDateTimestamp) => {
cy.enter_raw_proposal_body(closingDateTimestamp).as;
}
);
cy.contains('Transaction failed', proposalTimeout).should('be.visible'); cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should( cy.get(feedbackError).should('have.text', errorMsg);
'have.text',
'Network error: the network blocked the transaction through the spam protection'
);
cy.get(dialogCloseButton).click(); cy.get(dialogCloseButton).click();
}); });
// 3002-PROP-009 // 3002-PROP-009
it('Unable to create a proposal - when some but not enough tokens are associated', function () { it('Unable to create a proposal - when some but not enough tokens are associated', function () {
cy.ensure_specified_unstaked_tokens_are_associated(0.000001); const errorMsg =
cy.go_to_make_new_proposal(governanceProposalType.RAW); 'Network error: the network blocked the transaction through the spam protection: party has insufficient associated governance tokens in their staking account to submit proposal request (ABCI code 89)';
cy.create_ten_digit_unix_timestamp_for_specified_days('8').then(
(closingDateTimestamp) => { ensureSpecifiedUnstakedTokensAreAssociated('0.000001');
cy.enter_raw_proposal_body(closingDateTimestamp); goToMakeNewProposal(governanceProposalType.RAW);
} enterRawProposalBody(createTenDigitUnixTimeStampForSpecifiedDays(8));
);
cy.contains('Transaction failed', proposalTimeout).should('be.visible'); cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should( cy.get(feedbackError).should('have.text', errorMsg);
'have.text',
'Network error: the network blocked the transaction through the spam protection'
);
cy.get(dialogCloseButton).click(); cy.get(dialogCloseButton).click();
}); });
it('Unable to create a freeform proposal - when json parent section contains unexpected field', function () { it('Unable to create a freeform proposal - when json parent section contains unexpected field', function () {
const errorMsg =
'Invalid params: the transaction does not use a valid Vega command: unknown field unexpected" in vega.commands.v1.ProposalSubmission';
// 3001-VOTE-038 3002-PROP-013 3002-PROP-014 // 3001-VOTE-038 3002-PROP-013 3002-PROP-014
cy.go_to_make_new_proposal(governanceProposalType.RAW); goToMakeNewProposal(governanceProposalType.RAW);
cy.create_ten_digit_unix_timestamp_for_specified_days('8').then(
(closingDateTimestamp) => { cy.fixture('/proposals/raw.json').then((freeformProposal) => {
cy.fixture('/proposals/raw.json').then((freeformProposal) => { freeformProposal.terms.closingTimestamp =
freeformProposal.terms.closingTimestamp = closingDateTimestamp; createTenDigitUnixTimeStampForSpecifiedDays(8);
freeformProposal.unexpected = `i shouldn't be here`; freeformProposal.unexpected = `i shouldn't be here`;
let proposalPayload = JSON.stringify(freeformProposal); const proposalPayload = JSON.stringify(freeformProposal);
cy.get(rawProposalData).type(proposalPayload, { cy.get(rawProposalData).type(proposalPayload, {
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,
}); });
}); });
}
);
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.contains('Transaction failed', proposalTimeout).should('be.visible'); cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should( cy.get(feedbackError).should('have.text', errorMsg);
'have.text',
'Invalid params: the transaction is malformed'
);
cy.get(dialogCloseButton).click(); cy.get(dialogCloseButton).click();
cy.get(rawProposalData) cy.get(rawProposalData)
.invoke('val') .invoke('val')
@ -257,71 +259,64 @@ context(
it('Unable to create a freeform proposal - when json terms section contains unexpected field', function () { it('Unable to create a freeform proposal - when json terms section contains unexpected field', function () {
// 3001-VOTE-038 // 3001-VOTE-038
cy.go_to_make_new_proposal(governanceProposalType.RAW); const errorMsg =
cy.create_ten_digit_unix_timestamp_for_specified_days('8').then( 'Invalid params: the transaction does not use a valid Vega command: unknown field "unexpectedField" in vega.ProposalTerms';
(closingDateTimestamp) => {
cy.fixture('/proposals/raw.json').then((rawProposal) => {
rawProposal.terms.closingTimestamp = closingDateTimestamp;
rawProposal.terms.unexpectedField = `i shouldn't be here`;
let proposalPayload = JSON.stringify(rawProposal);
cy.get(rawProposalData).type(proposalPayload, { goToMakeNewProposal(governanceProposalType.RAW);
parseSpecialCharSequences: false,
delay: 2, cy.fixture('/proposals/raw.json').then((rawProposal) => {
}); rawProposal.terms.closingTimestamp =
}); createTenDigitUnixTimeStampForSpecifiedDays(8);
} rawProposal.terms.unexpectedField = `i shouldn't be here`;
); const proposalPayload = JSON.stringify(rawProposal);
cy.get(rawProposalData).type(proposalPayload, {
parseSpecialCharSequences: false,
delay: 2,
});
});
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.contains('Transaction failed', proposalTimeout).should('be.visible'); cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should( cy.get(feedbackError).should('have.text', errorMsg);
'have.text',
'Invalid params: the transaction is malformed'
);
cy.get(dialogCloseButton).click(); cy.get(dialogCloseButton).click();
}); });
// 1005-PROP-009 // 1005-PROP-009
it.skip( it('Unable to vote on a freeform proposal - when some but not enough vega associated', function () {
'Unable to vote on a freeform proposal - when some but not enough vega associated', const proposalTitle = generateFreeFormProposalTitle();
{ tags: '@smoke' },
function () {
const proposalTitle = generateFreeFormProposalTitle();
cy.ensure_specified_unstaked_tokens_are_associated(1); ensureSpecifiedUnstakedTokensAreAssociated('1');
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM); goToMakeNewProposal(governanceProposalType.FREEFORM);
cy.enter_unique_freeform_proposal_body('50', proposalTitle); enterUniqueFreeFormProposalBody('50', proposalTitle);
cy.wait_for_proposal_submitted(); waitForProposalSubmitted();
cy.staking_page_disassociate_tokens('0.0001'); stakingPageDisassociateTokens('0.0001');
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance).should('have.length', 1); cy.get(vegaWalletAssociatedBalance, txTimeout).should(
cy.get(vegaWalletAssociatedBalance, txTimeout).should( 'contain',
'contain', '0.9999'
'0.9999'
);
});
cy.navigate_to('proposals');
cy.get_submitted_proposal_from_proposal_list(proposalTitle).within(() =>
cy.get(viewProposalButton).click()
); );
cy.contains('Vote breakdown').should('be.visible', { });
timeout: 10000, navigateTo(navigation.proposals);
}); getSubmittedProposalFromProposalList(proposalTitle).within(() =>
cy.get(voteButtons).should('not.exist'); cy.get(viewProposalButton).click()
cy.getByTestId('min-proposal-requirements').should( );
'have.text', cy.contains('Vote breakdown').should('be.visible', {
`You must have at least ${this.minVoterBalance} VEGA associated to vote on this proposal` timeout: 10000,
); });
} cy.get(voteButtons).should('not.exist');
); cy.getByTestId('min-proposal-requirements').should(
'have.text',
`You must have at least ${this.minVoterBalance} VEGA associated to vote on this proposal`
);
});
it('Unable to vote on a proposal - when vega wallet disconnected - option to connect from within', function () { it('Unable to vote on a proposal - when vega wallet disconnected - option to connect from within', function () {
createRawProposal(); createRawProposal();
cy.get('[data-testid="manage-vega-wallet"]').click(); cy.get('[data-testid="manage-vega-wallet"]').click();
cy.get('[data-testid="disconnect"]').click(); cy.get('[data-testid="disconnect"]').click();
cy.get('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
cy.get_submitted_proposal_from_proposal_list( getSubmittedProposalFromProposalList(
rawProposal.rationale.title rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click()); ).within(() => cy.get(viewProposalButton).click());
}); });
@ -339,7 +334,7 @@ context(
'1.00', '1.00',
txTimeout txTimeout
); );
cy.vote_for_proposal('against'); voteForProposal('against');
// 3001-VOTE-079 // 3001-VOTE-079
cy.contains('You voted: Against').should('be.visible'); cy.contains('You voted: Against').should('be.visible');
}); });

View File

@ -1,3 +1,22 @@
import {
navigateTo,
navigation,
waitForSpinner,
} from '../../support/common.functions';
import {
getProposalInformationFromTable,
goToMakeNewProposal,
voteForProposal,
waitForProposalSubmitted,
} from '../../support/governance.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import {
vegaWalletSetSpecifiedApprovalAmount,
vegaWalletTeardown,
} from '../../support/wallet-teardown.functions';
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
const proposalListItem = '[data-testid="proposals-list-item"]'; const proposalListItem = '[data-testid="proposals-list-item"]';
const openProposals = '[data-testid="open-proposals"]'; const openProposals = '[data-testid="open-proposals"]';
const proposalType = '[data-testid="proposal-type"]'; const proposalType = '[data-testid="proposal-type"]';
@ -51,20 +70,20 @@ context(
before('connect wallets and set approval limit', function () { before('connect wallets and set approval limit', function () {
cy.createMarket(); cy.createMarket();
cy.visit('/'); cy.visit('/');
cy.vega_wallet_set_specified_approval_amount('1000'); vegaWalletSetSpecifiedApprovalAmount('1000');
}); });
beforeEach('visit governance tab', function () { beforeEach('visit governance tab', function () {
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.ethereum_wallet_connect(); ethereumWalletConnect();
cy.ensure_specified_unstaked_tokens_are_associated('1'); ensureSpecifiedUnstakedTokensAreAssociated('1');
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
}); });
it('Able to submit valid update network parameter proposal', function () { it('Able to submit valid update network parameter proposal', function () {
cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER); goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
// 3002-PROP-006 // 3002-PROP-006
cy.get(newProposalTitle).type('Test update network parameter proposal'); cy.get(newProposalTitle).type('Test update network parameter proposal');
// 3002-PROP-007 // 3002-PROP-007
@ -78,12 +97,12 @@ context(
cy.get(currentParameterValue).should('have.value', '2s'); cy.get(currentParameterValue).should('have.value', '2s');
cy.get(newProposedParameterValue).type('5s'); // 3007-PNEC-003 cy.get(newProposedParameterValue).type('5s'); // 3007-PNEC-003
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wait_for_proposal_submitted(); waitForProposalSubmitted();
}); });
it('Unable to submit network parameter with missing/invalid fields', function () { it('Unable to submit network parameter with missing/invalid fields', function () {
cy.navigate_to_page_if_not_already_loaded('proposals'); navigateTo(navigation.proposals);
cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER); goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.get(inputError).should('have.length', 3); cy.get(inputError).should('have.length', 3);
cy.get(newProposalTitle).type( cy.get(newProposalTitle).type(
@ -108,7 +127,7 @@ context(
it('Able to download network param proposal json', function () { it('Able to download network param proposal json', function () {
const downloadFolder = './cypress/downloads/'; const downloadFolder = './cypress/downloads/';
cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER); goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
cy.log('Download proposal file'); cy.log('Download proposal file');
cy.get(proposalDownloadBtn) cy.get(proposalDownloadBtn)
.should('be.visible') .should('be.visible')
@ -156,8 +175,8 @@ context(
}); });
it('Unable to submit network parameter proposal with vote deadline above enactment deadline', function () { it('Unable to submit network parameter proposal with vote deadline above enactment deadline', function () {
cy.navigate_to_page_if_not_already_loaded('proposals'); navigateTo(navigation.proposals);
cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER); goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
cy.get(newProposalTitle).type('Test update network parameter proposal'); cy.get(newProposalTitle).type('Test update network parameter proposal');
cy.get(newProposalDescription).type('invalid deadlines'); cy.get(newProposalDescription).type('invalid deadlines');
cy.get(proposalParameterSelect).select( cy.get(proposalParameterSelect).select(
@ -182,29 +201,32 @@ context(
// 3003-PMAN-001 // 3003-PMAN-001
it('Able to submit valid new market proposal', function () { it('Able to submit valid new market proposal', function () {
cy.go_to_make_new_proposal(governanceProposalType.NEW_MARKET); goToMakeNewProposal(governanceProposalType.NEW_MARKET);
cy.get(newProposalTitle).type('Test new market proposal'); cy.get(newProposalTitle).type('Test new market proposal');
cy.get(newProposalDescription).type('E2E test for proposals'); cy.get(newProposalDescription).type('E2E test for proposals');
cy.fixture('/proposals/new-market').then((newMarketProposal) => { cy.fixture('/proposals/new-market').then((newMarketProposal) => {
let newMarketPayload = JSON.stringify(newMarketProposal); const newMarketPayload = JSON.stringify(newMarketProposal);
cy.get(newProposalTerms).type(newMarketPayload, { cy.get(newProposalTerms).type(newMarketPayload, {
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,
}); });
}); });
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wait_for_proposal_submitted(); waitForProposalSubmitted();
}); });
it('Unable to submit new market proposal with missing/invalid fields', function () { it('Unable to submit new market proposal with missing/invalid fields', function () {
cy.go_to_make_new_proposal(governanceProposalType.NEW_MARKET); const errorMsg =
'Invalid params: the transaction is not a valid Vega command: unknown field "filters" in vega.DataSourceDefinition';
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.get(inputError).should('have.length', 3); cy.get(inputError).should('have.length', 3);
cy.get(newProposalTitle).type('Test new market proposal'); cy.get(newProposalTitle).type('Test new market proposal');
cy.get(newProposalDescription).type('E2E test for proposals'); cy.get(newProposalDescription).type('E2E test for proposals');
cy.fixture('/proposals/new-market').then((newMarketProposal) => { cy.fixture('/proposals/new-market').then((newMarketProposal) => {
newMarketProposal.invalid = 'I am an invalid field'; newMarketProposal.invalid = 'I am an invalid field';
let newMarketPayload = JSON.stringify(newMarketProposal); const newMarketPayload = JSON.stringify(newMarketProposal);
cy.get(newProposalTerms).type(newMarketPayload, { cy.get(newProposalTerms).type(newMarketPayload, {
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,
@ -212,21 +234,18 @@ context(
}); });
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.contains('Transaction failed', proposalTimeout).should('be.visible'); cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should( cy.get(feedbackError).should('have.text', errorMsg);
'have.text',
'Invalid params: the transaction is not a valid Vega command: unknown field "invalid" in vega.NewMarket'
);
}); });
// Will fail if run after 'Able to submit update market proposal and vote for proposal' // Will fail if run after 'Able to submit update market proposal and vote for proposal'
// 3002-PROP-022 // 3002-PROP-022
it('Unable to submit update market proposal without equity-like share in the market', function () { it('Unable to submit update market proposal without equity-like share in the market', function () {
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_MARKET); goToMakeNewProposal(governanceProposalType.UPDATE_MARKET);
cy.get(newProposalTitle).type('Test update market proposal - rejected'); cy.get(newProposalTitle).type('Test update market proposal - rejected');
cy.get(newProposalDescription).type('E2E test for proposals'); cy.get(newProposalDescription).type('E2E test for proposals');
cy.get(proposalMarketSelect).select('Test market 1'); cy.get(proposalMarketSelect).select('Test market 1');
cy.fixture('/proposals/update-market').then((updateMarketProposal) => { cy.fixture('/proposals/update-market').then((updateMarketProposal) => {
let newUpdateMarketProposal = JSON.stringify(updateMarketProposal); const newUpdateMarketProposal = JSON.stringify(updateMarketProposal);
cy.get(newProposalTerms).type(newUpdateMarketProposal, { cy.get(newProposalTerms).type(newUpdateMarketProposal, {
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,
@ -237,23 +256,23 @@ context(
cy.getByTestId('dialog-content') cy.getByTestId('dialog-content')
.find('p') .find('p')
.should('have.text', 'PROPOSAL_ERROR_INSUFFICIENT_EQUITY_LIKE_SHARE'); .should('have.text', 'PROPOSAL_ERROR_INSUFFICIENT_EQUITY_LIKE_SHARE');
cy.ensure_specified_unstaked_tokens_are_associated('1'); ensureSpecifiedUnstakedTokensAreAssociated('1');
}); });
// 3002-PROP-020 // 3002-PROP-020
it('Unable to submit update market proposal without minimum amount of tokens', function () { it('Unable to submit update market proposal without minimum amount of tokens', function () {
cy.vega_wallet_teardown(); vegaWalletTeardown();
cy.vega_wallet_faucet_assets_without_check( vegaWalletFaucetAssetsWithoutCheck(
'fUSDC', 'fUSDC',
'1000000', '1000000',
vegaWalletPublicKey vegaWalletPublicKey
); );
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_MARKET); goToMakeNewProposal(governanceProposalType.UPDATE_MARKET);
cy.get(newProposalTitle).type('Test update market proposal - rejected'); cy.get(newProposalTitle).type('Test update market proposal - rejected');
cy.get(newProposalDescription).type('E2E test for proposals'); cy.get(newProposalDescription).type('E2E test for proposals');
cy.get(proposalMarketSelect).select('Test market 1'); cy.get(proposalMarketSelect).select('Test market 1');
cy.fixture('/proposals/update-market').then((updateMarketProposal) => { cy.fixture('/proposals/update-market').then((updateMarketProposal) => {
let newUpdateMarketProposal = JSON.stringify(updateMarketProposal); const newUpdateMarketProposal = JSON.stringify(updateMarketProposal);
cy.get(newProposalTerms).type(newUpdateMarketProposal, { cy.get(newProposalTerms).type(newUpdateMarketProposal, {
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,
@ -269,12 +288,12 @@ context(
// 3001-VOTE-092 // 3001-VOTE-092
it('Able to submit update market proposal and vote for proposal', function () { it('Able to submit update market proposal and vote for proposal', function () {
cy.vega_wallet_faucet_assets_without_check( vegaWalletFaucetAssetsWithoutCheck(
'fUSDC', 'fUSDC',
'1000000', '1000000',
vegaWalletPublicKey vegaWalletPublicKey
); );
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_MARKET); goToMakeNewProposal(governanceProposalType.UPDATE_MARKET);
cy.get(newProposalTitle).type('Test update market proposal'); cy.get(newProposalTitle).type('Test update market proposal');
cy.get(newProposalDescription).type('E2E test for proposals'); cy.get(newProposalDescription).type('E2E test for proposals');
cy.get(proposalMarketSelect).select('Test market 1'); cy.get(proposalMarketSelect).select('Test market 1');
@ -285,20 +304,20 @@ context(
cy.get('dd').eq(2).invoke('text').as('EnactedMarketId'); cy.get('dd').eq(2).invoke('text').as('EnactedMarketId');
}); });
cy.get('@EnactedMarketId').then((marketId) => { cy.get('@EnactedMarketId').then((marketId) => {
cy.VegaWalletSubmitLiquidityProvision(marketId, '1'); cy.VegaWalletSubmitLiquidityProvision(String(marketId), '1');
}); });
cy.fixture('/proposals/update-market').then((updateMarketProposal) => { cy.fixture('/proposals/update-market').then((updateMarketProposal) => {
let newUpdateMarketProposal = JSON.stringify(updateMarketProposal); const newUpdateMarketProposal = JSON.stringify(updateMarketProposal);
cy.get(newProposalTerms).type(newUpdateMarketProposal, { cy.get(newProposalTerms).type(newUpdateMarketProposal, {
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,
}); });
}); });
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wait_for_proposal_submitted(); waitForProposalSubmitted();
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
cy.get('@EnactedMarketId').then((marketId) => { cy.get('@EnactedMarketId').then((marketId) => {
cy.contains(marketId) cy.contains(String(marketId))
.parentsUntil(proposalListItem) .parentsUntil(proposalListItem)
.within(() => { .within(() => {
cy.getByTestId(viewProposalBtn).click(); cy.getByTestId(viewProposalBtn).click();
@ -312,7 +331,7 @@ context(
'contain.text', 'contain.text',
'Currently expected to fail' 'Currently expected to fail'
); );
cy.vote_for_proposal('for'); voteForProposal('for');
cy.getByTestId(liquidityVoteStatus).should( cy.getByTestId(liquidityVoteStatus).should(
'contain.text', 'contain.text',
'Currently expected to pass' 'Currently expected to pass'
@ -321,18 +340,18 @@ context(
'contain.text', 'contain.text',
'Currently expected to pass' 'Currently expected to pass'
); );
cy.get_proposal_information_from_table('Expected to pass') getProposalInformationFromTable('Expected to pass')
.contains('👍 by Token vote') .contains('👍 by Token vote')
.should('be.visible'); .should('be.visible');
}); });
// 3001-VOTE-026 3001-VOTE-027 3001-VOTE-028 3001-VOTE-095 3001-VOTE-096 3005-PASN-001 // 3001-VOTE-026 3001-VOTE-027 3001-VOTE-028 3001-VOTE-095 3001-VOTE-096 3005-PASN-001
it('Able to submit new asset proposal using min deadlines', function () { it('Able to submit new asset proposal using min deadlines', function () {
cy.go_to_make_new_proposal(governanceProposalType.NEW_ASSET); goToMakeNewProposal(governanceProposalType.NEW_ASSET);
cy.get(newProposalTitle).type('Test new asset proposal'); cy.get(newProposalTitle).type('Test new asset proposal');
cy.get(newProposalDescription).type('E2E test for proposals'); cy.get(newProposalDescription).type('E2E test for proposals');
cy.fixture('/proposals/new-asset').then((newAssetProposal) => { cy.fixture('/proposals/new-asset').then((newAssetProposal) => {
let newAssetPayload = JSON.stringify(newAssetProposal); const newAssetPayload = JSON.stringify(newAssetProposal);
cy.get(newProposalTerms).type(newAssetPayload, { cy.get(newProposalTerms).type(newAssetPayload, {
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,
@ -361,7 +380,7 @@ context(
}); });
it('Unable to submit new asset proposal with missing/invalid fields', function () { it('Unable to submit new asset proposal with missing/invalid fields', function () {
cy.go_to_make_new_proposal(governanceProposalType.NEW_ASSET); goToMakeNewProposal(governanceProposalType.NEW_ASSET);
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.get(inputError).should('have.length', 3); cy.get(inputError).should('have.length', 3);
cy.get(newProposalTitle).type('Invalid new asset proposal'); cy.get(newProposalTitle).type('Invalid new asset proposal');
@ -377,13 +396,13 @@ context(
const assetId = const assetId =
'ebcd94151ae1f0d39a4bde3b21a9c7ae81a80ea4352fb075a92e07608d9c953d'; 'ebcd94151ae1f0d39a4bde3b21a9c7ae81a80ea4352fb075a92e07608d9c953d';
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_ASSET); goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
enterUpdateAssetProposalDetails(); enterUpdateAssetProposalDetails();
cy.get(minVoteDeadline).click(); cy.get(minVoteDeadline).click();
cy.get(minEnactDeadline).click(); cy.get(minEnactDeadline).click();
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wait_for_proposal_submitted(); waitForProposalSubmitted();
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
cy.get(openProposals).within(() => { cy.get(openProposals).within(() => {
cy.get(proposalType) cy.get(proposalType)
.contains('Update asset') .contains('Update asset')
@ -393,22 +412,22 @@ context(
cy.getByTestId(viewProposalBtn).click(); cy.getByTestId(viewProposalBtn).click();
}); });
}); });
cy.get_proposal_information_from_table('Proposed enactment') // 3001-VOTE-044 getProposalInformationFromTable('Proposed enactment') // 3001-VOTE-044
.invoke('text') .invoke('text')
.should('not.be.empty'); .should('not.be.empty');
}); });
it('Able to submit update asset proposal using max deadline', function () { it('Able to submit update asset proposal using max deadline', function () {
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_ASSET); goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
enterUpdateAssetProposalDetails(); enterUpdateAssetProposalDetails();
cy.get(maxVoteDeadline).click(); cy.get(maxVoteDeadline).click();
cy.get(maxEnactDeadline).click(); cy.get(maxEnactDeadline).click();
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wait_for_proposal_submitted(); waitForProposalSubmitted();
}); });
it('Unable to submit edit asset proposal with missing/invalid fields', function () { it('Unable to submit edit asset proposal with missing/invalid fields', function () {
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_ASSET); goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.get(inputError).should('have.length', 3); cy.get(inputError).should('have.length', 3);
}); });
@ -428,7 +447,7 @@ context(
cy.get(newProposalTitle).type('Test update asset proposal'); cy.get(newProposalTitle).type('Test update asset proposal');
cy.get(newProposalDescription).type('E2E test for proposals'); cy.get(newProposalDescription).type('E2E test for proposals');
cy.fixture('/proposals/update-asset').then((newAssetProposal) => { cy.fixture('/proposals/update-asset').then((newAssetProposal) => {
let newAssetPayload = JSON.stringify(newAssetProposal); const newAssetPayload = JSON.stringify(newAssetProposal);
cy.get(newProposalTerms).type(newAssetPayload, { cy.get(newProposalTerms).type(newAssetPayload, {
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,

View File

@ -1,9 +1,28 @@
import type { testFreeformProposal } from '../../support/common-interfaces';
import {
navigateTo,
navigation,
waitForSpinner,
} from '../../support/common.functions';
import { import {
createFreeformProposal, createFreeformProposal,
createRawProposal, createRawProposal,
createTenDigitUnixTimeStampForSpecifiedDays,
enterRawProposalBody,
generateFreeFormProposalTitle, generateFreeFormProposalTitle,
getProposalIdFromList,
getProposalInformationFromTable,
getSortOrderOfSuppliedArray,
getSubmittedProposalFromProposalList,
goToMakeNewProposal,
governanceProposalType, governanceProposalType,
voteForProposal,
waitForProposalSubmitted,
waitForProposalSync,
} from '../../support/governance.functions'; } from '../../support/governance.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
const proposalDetailsTitle = '[data-testid="proposal-title"]'; const proposalDetailsTitle = '[data-testid="proposal-title"]';
const openProposals = '[data-testid="open-proposals"]'; const openProposals = '[data-testid="open-proposals"]';
@ -12,17 +31,17 @@ const viewProposalButton = '[data-testid="view-proposal-btn"]';
describe('Governance flow for proposal list', { tags: '@slow' }, function () { describe('Governance flow for proposal list', { tags: '@slow' }, function () {
before('connect wallets and set approval limit', function () { before('connect wallets and set approval limit', function () {
cy.vega_wallet_set_specified_approval_amount('1000'); vegaWalletSetSpecifiedApprovalAmount('1000');
cy.visit('/'); cy.visit('/');
}); });
beforeEach('visit proposals tab', function () { beforeEach('visit proposals tab', function () {
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.ethereum_wallet_connect(); ethereumWalletConnect();
cy.ensure_specified_unstaked_tokens_are_associated(1); ensureSpecifiedUnstakedTokensAreAssociated('1');
cy.navigate_to_page_if_not_already_loaded('proposals'); navigateTo(navigation.proposals);
}); });
it('Newly created proposals list - proposals closest to closing date appear higher in list', function () { it('Newly created proposals list - proposals closest to closing date appear higher in list', function () {
@ -30,32 +49,30 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
const maxCloseDays = 3; const maxCloseDays = 3;
// 3001-VOTE-005 // 3001-VOTE-005
let proposalDays = [ const proposalDays = [
minCloseDays + 1, minCloseDays + 1,
maxCloseDays, maxCloseDays,
minCloseDays + 3, minCloseDays + 3,
minCloseDays + 2, minCloseDays + 2,
]; ];
for (var index = 0; index < proposalDays.length; index++) { for (let index = 0; index < proposalDays.length; index++) {
cy.go_to_make_new_proposal(governanceProposalType.RAW); goToMakeNewProposal(governanceProposalType.RAW);
cy.create_ten_digit_unix_timestamp_for_specified_days( enterRawProposalBody(
proposalDays[index] createTenDigitUnixTimeStampForSpecifiedDays(proposalDays[index])
).then((closingDateTimestamp) => { );
cy.enter_raw_proposal_body(closingDateTimestamp); waitForProposalSubmitted();
}); waitForProposalSync();
cy.wait_for_proposal_submitted();
cy.wait_for_proposal_sync();
} }
let arrayOfProposals = []; const arrayOfProposals: string[] = [];
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
cy.get(proposalDetailsTitle) cy.get(proposalDetailsTitle)
.each((proposalTitleElement) => { .each((proposalTitleElement) => {
arrayOfProposals.push(proposalTitleElement.text()); arrayOfProposals.push(proposalTitleElement.text());
}) })
.then(() => { .then(() => {
cy.get_sort_order_of_supplied_array(arrayOfProposals).should( cy.wrap(getSortOrderOfSuppliedArray(arrayOfProposals)).should(
'equal', 'equal',
'descending' 'descending'
); );
@ -67,7 +84,7 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
const proposalTitle = generateFreeFormProposalTitle(); const proposalTitle = generateFreeFormProposalTitle();
createFreeformProposal(proposalTitle); createFreeformProposal(proposalTitle);
cy.get_proposal_id_from_list(proposalTitle); getProposalIdFromList(proposalTitle);
cy.get('@proposalIdText').then((proposalId) => { cy.get('@proposalIdText').then((proposalId) => {
cy.get('[data-testid="set-proposals-filter-visible"]').click(); cy.get('[data-testid="set-proposals-filter-visible"]').click();
cy.get('[data-testid="filter-input"]').type(proposerId); cy.get('[data-testid="filter-input"]').type(proposerId);
@ -77,8 +94,8 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
it('Newly created proposals list - shows title and portion of summary', function () { it('Newly created proposals list - shows title and portion of summary', function () {
createRawProposal(this.minProposerBalance); // 3001-VOTE-052 createRawProposal(this.minProposerBalance); // 3001-VOTE-052
cy.get('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
cy.get_proposal_id_from_list(rawProposal.rationale.title); getProposalIdFromList(rawProposal.rationale.title);
cy.get('@proposalIdText').then((proposalId) => { cy.get('@proposalIdText').then((proposalId) => {
cy.get(openProposals).within(() => { cy.get(openProposals).within(() => {
// 3001-VOTE-008 // 3001-VOTE-008
@ -102,21 +119,22 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
// 3001-VOTE-004 // 3001-VOTE-004
// 3001-VOTE-035 // 3001-VOTE-035
createRawProposal(this.minProposerBalance); createRawProposal(this.minProposerBalance);
cy.get('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
cy.get_submitted_proposal_from_proposal_list( getSubmittedProposalFromProposalList(rawProposal.rationale.title).within(
rawProposal.rationale.title () => {
).within(() => { cy.get(viewProposalButton).should('be.visible').click();
cy.get(viewProposalButton).should('be.visible').click(); }
}); );
cy.get('@proposalIdText').then((proposalId) => { cy.get('@proposalIdText').then((proposalId) => {
cy.get_proposal_information_from_table('ID') getProposalInformationFromTable('ID')
.contains(proposalId) .contains(String(proposalId))
.and('be.visible'); .and('be.visible');
}); });
cy.get_proposal_information_from_table('State') getProposalInformationFromTable('State')
.contains('Open') .contains('Open')
.and('be.visible'); .and('be.visible');
cy.get_proposal_information_from_table('Type') getProposalInformationFromTable('Type')
.contains('Freeform') .contains('Freeform')
.and('be.visible'); .and('be.visible');
}); });
@ -125,38 +143,21 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
// 3001-VOTE-071 // 3001-VOTE-071
it('Newly created freeform proposals list - shows proposal participation - both met and not', function () { it('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
const proposalTitle = generateFreeFormProposalTitle(); const proposalTitle = generateFreeFormProposalTitle();
const requiredParticipation = 0.001;
createFreeformProposal(proposalTitle); createFreeformProposal(proposalTitle);
getSubmittedProposalFromProposalList(proposalTitle).within(() => {
cy.get_submitted_proposal_from_proposal_list(proposalTitle) // 3001-VOTE-039
.as('submittedProposal') cy.get(voteStatus).should('have.text', 'Participation not reached');
.within(() => { cy.get(viewProposalButton).click();
// 3001-VOTE-039 });
cy.get(voteStatus).should('have.text', 'Participation not reached'); voteForProposal('for');
cy.get(viewProposalButton).click(); navigateTo(navigation.proposals);
}); getSubmittedProposalFromProposalList(proposalTitle).within(() => {
cy.vote_for_proposal('for'); cy.get(voteStatus).should('have.text', 'Set to pass');
cy.get_proposal_information_from_table('Total Supply') cy.get(viewProposalButton).click();
.invoke('text') });
.then((totalSupply) => { getProposalInformationFromTable('Token participation met')
let tokensRequiredToAchieveResult = parseFloat( .contains('👍')
(totalSupply.replace(/,/g, '') * requiredParticipation) / 100 .should('be.visible');
).toFixed(2);
cy.ensure_specified_unstaked_tokens_are_associated(
tokensRequiredToAchieveResult
);
cy.navigate_to_page_if_not_already_loaded('proposals');
cy.get('@submittedProposal').within(() =>
cy.get(viewProposalButton).click()
);
cy.get_proposal_information_from_table('Token participation met')
.contains('👍')
.should('be.visible');
cy.navigate_to('proposals');
cy.get('@submittedProposal').within(() =>
cy.get(voteStatus).should('have.text', 'Set to pass')
);
});
}); });
}); });

View File

@ -1,3 +1,21 @@
import {
navigateTo,
navigation,
waitForSpinner,
} from '../../support/common.functions';
import {
clickOnValidatorFromList,
closeStakingDialog,
stakingPageAssociateTokens,
stakingValidatorPageAddStake,
waitForBeginningOfEpoch,
} from '../../support/staking.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import {
depositAsset,
vegaWalletTeardown,
} from '../../support/wallet-teardown.functions';
const vegaAssetAddress = '0x67175Da1D5e966e40D11c4B2519392B2058373de'; const vegaAssetAddress = '0x67175Da1D5e966e40D11c4B2519392B2058373de';
const vegaWalletUnstakedBalance = const vegaWalletUnstakedBalance =
'[data-testid="vega-wallet-balance-unstaked"]'; '[data-testid="vega-wallet-balance-unstaked"]';
@ -8,29 +26,29 @@ const rewardsTimeOut = { timeout: 60000 };
context('rewards - flow', { tags: '@slow' }, function () { context('rewards - flow', { tags: '@slow' }, function () {
before('set up environment to allow rewards', function () { before('set up environment to allow rewards', function () {
cy.visit('/'); cy.visit('/');
cy.wait_for_spinner(); waitForSpinner();
cy.deposit_asset(vegaAssetAddress, '1000'); depositAsset(vegaAssetAddress, '1000');
cy.validatorsSelfDelegate(); cy.validatorsSelfDelegate();
cy.ethereum_wallet_connect(); ethereumWalletConnect();
cy.connectVegaWallet(); cy.connectVegaWallet();
topUpRewardsPool(); cy.VegaWalletTopUpRewardsPool(30, 200);
cy.navigate_to('validators'); navigateTo(navigation.validators);
cy.vega_wallet_teardown(); vegaWalletTeardown();
cy.staking_page_associate_tokens('6000'); stakingPageAssociateTokens('6000');
cy.get(vegaWalletUnstakedBalance, txTimeout).should( cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain', 'contain',
'6,000.0', '6,000.0',
txTimeout txTimeout
); );
cy.get('button').contains('Select a validator to nominate').click(); cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0); clickOnValidatorFromList(0);
cy.staking_validator_page_add_stake('3000'); stakingValidatorPageAddStake('3000');
cy.close_staking_dialog(); closeStakingDialog();
cy.navigate_to('validators'); navigateTo(navigation.validators);
cy.click_on_validator_from_list(1); clickOnValidatorFromList(1);
cy.staking_validator_page_add_stake('3000'); stakingValidatorPageAddStake('3000');
cy.close_staking_dialog(); closeStakingDialog();
cy.navigate_to('rewards'); navigateTo(navigation.rewards);
}); });
it('Should display rewards per epoch', function () { it('Should display rewards per epoch', function () {
@ -54,7 +72,7 @@ context('rewards - flow', { tags: '@slow' }, function () {
.within(() => { .within(() => {
cy.get('h2').first().invoke('text').as('epochNumber'); cy.get('h2').first().invoke('text').as('epochNumber');
}); });
cy.wait_for_beginning_of_epoch(); waitForBeginningOfEpoch();
cy.get('@epochNumber').then((epochNumber) => { cy.get('@epochNumber').then((epochNumber) => {
cy.getByTestId(rewardsTable) cy.getByTestId(rewardsTable)
.first() .first()
@ -76,28 +94,12 @@ context('rewards - flow', { tags: '@slow' }, function () {
cy.get('h2').first().should('contain.text', 'EPOCH'); cy.get('h2').first().should('contain.text', 'EPOCH');
cy.getByTestId('individual-rewards-asset').should('have.text', 'Vega'); cy.getByTestId('individual-rewards-asset').should('have.text', 'Vega');
cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD') cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD')
.should('contain.text', '0.4415') .should('contain.text', '0.1177')
.and('contain.text', '(44.15%)'); .and('contain.text', '(11.7733%)');
cy.getByTestId('ACCOUNT_TYPE_FEES_INFRASTRUCTURE') cy.getByTestId('ACCOUNT_TYPE_FEES_INFRASTRUCTURE')
.should('contain.text', '0.0004') .should('contain.text', '0.0001')
.and('contain.text', '(44.15%)'); .and('contain.text', '(11.7733%)');
cy.getByTestId('total').should('have.text', '0.4419'); cy.getByTestId('total').should('have.text', '0.1179');
}); });
}); });
function topUpRewardsPool() {
// Must ensure that test wallet contains assets already and that the tests are within the start and end epochs
cy.exec(
`vega wallet transaction send --wallet ${Cypress.env(
'vegaWalletName'
)} --pubkey ${Cypress.env(
'vegaWalletPublicKey'
)} -p "./src/fixtures/wallet/passphrase" --network DV '{"transfer":{"fromAccountType":4,"toAccountType":12,"to":"0000000000000000000000000000000000000000000000000000000000000000","asset":"b4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b","amount":"1000000000000000000","recurring":{"startEpoch":30, "endEpoch": 200, "factor":"1"}}}' --home ${Cypress.env(
'vegaWalletLocation'
)}`,
{ failOnNonZeroExit: false }
)
.its('stderr')
.should('contain', '');
}
}); });

View File

@ -1,876 +0,0 @@
/// <reference types="cypress" />
const stakeValidatorListTotalStake = '[col-id="stake"] > div > span';
const stakeValidatorListTotalShare = '[col-id="stakeShare"] > div > span';
const stakeValidatorListValidatorStake = '[col-id="stake"] > div > span';
const stakeRemoveStakeRadioButton = '[data-testid="remove-stake-radio"]';
const stakeTokenAmountInputBox = '[data-testid="token-amount-input"]';
const stakeTokenSubmitButton = '[data-testid="token-input-submit-button"]';
const stakeNextEpochValue = '[data-testid="stake-next-epoch"]';
const stakeThisEpochValue = '[data-testid="stake-this-epoch"]';
const stakeAddStakeRadioButton = '[data-testid="add-stake-radio"]';
const stakeMaximumTokens = '[data-testid="token-amount-use-maximum"]';
const totalStake = '[data-testid="total-stake"]';
const stakeShare = '[data-testid="stake-percentage"]';
const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort');
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
const vegaWalletUnstakedBalance =
'[data-testid="vega-wallet-balance-unstaked"]:visible';
const vegaWalletStakedBalances =
'[data-testid="vega-wallet-balance-staked-validators"]';
const ethWalletAssociatedBalances =
'[data-testid="eth-wallet-associated-balances"]';
const ethWalletTotalAssociatedBalance =
'[data-testid="currency-locked"]:visible';
const ethWalletContainer = '[data-testid="ethereum-wallet"]:visible';
const vegaWallet = '[data-testid="vega-wallet"]';
const partValidatorId = '…';
const txTimeout = Cypress.env('txTimeout');
const epochTimeout = Cypress.env('epochTimeout');
context(
'Staking Tab - with eth and vega wallets connected',
{ tags: '@slow' },
function () {
// 2001-STKE-002, 2001-STKE-032
before('visit staking tab and connect vega wallet', function () {
cy.visit('/');
cy.vega_wallet_set_specified_approval_amount('1000');
});
describe('Eth wallet - contains VEGA tokens', function () {
beforeEach(
'teardown wallet & drill into a specific validator',
function () {
cy.reload();
cy.wait_for_spinner();
cy.connectVegaWallet();
cy.ethereum_wallet_connect();
cy.vega_wallet_teardown();
cy.navigate_to('validators');
}
);
it('Able to stake against a validator - using vega from wallet', function () {
cy.staking_page_associate_tokens('3');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('3.0', txTimeout)
.should('be.visible');
cy.get(ethWalletAssociatedBalances, txTimeout)
.contains(vegaWalletPublicKeyShort, txTimeout)
.parent()
.should('contain', 3.0, txTimeout);
cy.get('button').contains('Select a validator to nominate').click();
// 2001-STKE-031
cy.click_on_validator_from_list(0);
// 2001-STKE-033, 2001-STKE-034, 2001-STKE-037
cy.staking_validator_page_add_stake('2');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
// 2001-STKE-039
cy.get(vegaWalletStakedBalances, txTimeout)
.should('contain', 2.0, txTimeout)
.and('contain', partValidatorId);
cy.get(stakeNextEpochValue, epochTimeout) // 2001-STKE-016 2001-STKE-038
.contains(2.0, epochTimeout)
.should('be.visible');
cy.get(stakeThisEpochValue, epochTimeout) // 2001-STKE-013
.contains(2.0, epochTimeout)
.should('be.visible');
cy.close_staking_dialog();
cy.navigate_to('validators');
// 2002-SINC-007
cy.validate_validator_list_total_stake_and_share(
'0',
'2.00',
'100.00%'
);
});
it('Able to stake against a validator - using vega from vesting contract', function () {
cy.staking_page_associate_tokens('3', { type: 'contract' });
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('3.0', txTimeout)
.should('be.visible');
cy.get(ethWalletAssociatedBalances, txTimeout)
.contains(vegaWalletPublicKeyShort, txTimeout)
.parent()
.should('contain', 3.0, txTimeout);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('2');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout)
.should('contain', 2.0, txTimeout)
.and('contain', partValidatorId);
cy.get(stakeNextEpochValue, epochTimeout)
.contains(2.0, epochTimeout)
.should('be.visible');
cy.get(stakeThisEpochValue, epochTimeout)
.contains(2.0, epochTimeout)
.should('be.visible');
cy.close_staking_dialog();
cy.navigate_to('validators');
cy.validate_validator_list_total_stake_and_share(
'0',
'2.00',
'100.00%'
);
});
it('Able to stake against a validator - using vega from both wallet and vesting contract', function () {
cy.staking_page_associate_tokens('3', { type: 'contract' });
cy.navigate_to('validators');
cy.staking_page_associate_tokens('4', { type: 'wallet' });
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
7.0,
txTimeout
);
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('3.0', txTimeout)
.should('be.visible');
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('4.0', txTimeout)
.should('be.visible');
cy.get(ethWalletAssociatedBalances, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get(ethWalletAssociatedBalances, txTimeout).should(
'contain',
4.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('6');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout)
.should('contain', 6.0, txTimeout)
.and('contain', partValidatorId);
cy.get(stakeNextEpochValue, epochTimeout)
.contains(6.0, epochTimeout)
.should('be.visible');
cy.get(stakeThisEpochValue, epochTimeout)
.contains(6.0, epochTimeout)
.should('be.visible');
cy.close_staking_dialog();
cy.navigate_to('validators');
cy.validate_validator_list_total_stake_and_share(
'0',
'6.00',
'100.00%'
);
});
it('Able to stake against multiple validators', function () {
cy.staking_page_associate_tokens('5');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
5.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('2');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout)
.parent()
.should('contain', 2.0, txTimeout);
cy.close_staking_dialog();
cy.navigate_to('validators');
cy.click_on_validator_from_list(1);
cy.staking_validator_page_add_stake('1');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
2.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout)
.should('have.length', 2, txTimeout)
.eq(0)
.should('contain', 2.0, txTimeout);
cy.get(vegaWalletStakedBalances, txTimeout)
.eq(1)
.should('contain', 1.0, txTimeout);
cy.close_staking_dialog();
cy.navigate_to('validators');
cy.get(`[row-id="${0}"]`).within(() => {
cy.get(stakeValidatorListTotalStake)
.should('have.text', '2.00')
.and('be.visible');
cy.get(stakeValidatorListTotalShare)
.should('have.text', '66.67%')
.and('be.visible');
cy.get(stakeValidatorListValidatorStake)
.scrollIntoView()
.should('have.text', '2.00')
.and('be.visible');
});
cy.get(`[row-id="${1}"]`).within(() => {
cy.get(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '1.00')
.and('be.visible');
cy.get(stakeValidatorListTotalShare)
.should('have.text', '33.33%')
.and('be.visible');
cy.get(stakeValidatorListValidatorStake)
.scrollIntoView()
.should('have.text', '1.00')
.and('be.visible');
});
});
// 2001-STKE-041
it(
'Able to remove part of a stake against a validator',
{ tags: '@smoke' },
function () {
cy.staking_page_associate_tokens('4');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
4.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('3');
cy.get(stakeNextEpochValue, epochTimeout)
.contains(3.0, epochTimeout)
.should('be.visible');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
cy.close_staking_dialog();
cy.navigate_to('validators');
// 2001-STKE-040
cy.click_on_validator_from_list(0);
// 2001-STKE-044, 2001-STKE-048
cy.staking_validator_page_remove_stake('1');
// 2001-STKE-049
cy.get(stakeNextEpochValue, epochTimeout).contains(2.0, epochTimeout);
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
2.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
2.0,
txTimeout
);
cy.get(stakeNextEpochValue, epochTimeout)
.contains(2.0, epochTimeout)
.should('be.visible');
cy.get(stakeThisEpochValue, epochTimeout)
.contains(2.0, epochTimeout)
.should('be.visible');
cy.get(totalStake, epochTimeout).should('contain.text', '2');
cy.get(stakeShare, epochTimeout).should('have.text', '100%');
cy.navigate_to('validators');
cy.validate_validator_list_total_stake_and_share(
'0',
'2.00',
'100.00%'
);
}
);
// 2001-STKE-045
it('Able to remove a full stake against a validator', function () {
cy.staking_page_associate_tokens('3');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('1');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
2.0,
txTimeout
);
cy.close_staking_dialog();
cy.navigate_to('validators');
cy.click_on_validator_from_list('0');
cy.staking_validator_page_remove_stake('1');
cy.get(stakeNextEpochValue, epochTimeout)
.contains(0.0, epochTimeout)
.should('be.visible');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get(stakeNextEpochValue, epochTimeout)
.contains(0.0, epochTimeout)
.should('be.visible');
cy.get(stakeThisEpochValue, epochTimeout)
.contains(0.0, epochTimeout)
.should('be.visible');
cy.get(vegaWalletStakedBalances, txTimeout).should(
'not.exist',
txTimeout
);
cy.navigate_to('validators');
cy.validate_validator_list_total_stake_and_share('0', '0.00', '0.00%');
});
it('Unable to remove a stake with a negative value for a validator', function () {
cy.staking_page_associate_tokens('3');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('2');
cy.get(stakeNextEpochValue, epochTimeout)
.contains(2.0, epochTimeout)
.should('be.visible');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
cy.close_staking_dialog();
cy.navigate_to('validators');
cy.click_on_validator_from_list(0);
cy.get(stakeRemoveStakeRadioButton, txTimeout).click();
cy.get(stakeTokenAmountInputBox).type('-0.1');
cy.contains('Waiting for next epoch to start', epochTimeout);
cy.get(stakeTokenSubmitButton)
.should('be.disabled', epochTimeout)
.and('contain', `Remove -0.1 $VEGA tokens at the end of epoch`)
.and('be.visible');
});
it('Unable to remove a stake greater than staked amount next epoch for a validator', function () {
cy.staking_page_associate_tokens('3');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('2');
cy.get(stakeNextEpochValue, epochTimeout)
.contains(2.0, epochTimeout)
.should('be.visible');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
cy.close_staking_dialog();
cy.navigate_to('validators');
cy.click_on_validator_from_list(0);
cy.get(stakeRemoveStakeRadioButton).click();
cy.get(stakeTokenAmountInputBox).type(4);
cy.contains('Waiting for next epoch to start', epochTimeout);
cy.get(stakeTokenSubmitButton)
.should('be.disabled', epochTimeout)
.and('contain', `Remove 4 $VEGA tokens at the end of epoch`)
.and('be.visible');
});
it('Disassociating all wallet tokens max - removes all staked tokens', function () {
cy.staking_page_associate_tokens('3');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list('1');
cy.staking_validator_page_add_stake('2');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
2.0,
txTimeout
);
cy.close_staking_dialog();
cy.staking_page_disassociate_all_tokens('wallet');
cy.get(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, txTimeout).should('not.exist');
});
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('0.0', txTimeout)
.should('be.visible');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.00'
);
});
cy.get(vegaWalletStakedBalances, txTimeout).should(
'not.exist',
txTimeout
);
cy.navigate_to('validators');
cy.validate_validator_list_total_stake_and_share('0', '0.00', '0.00%');
});
it('Disassociating all vesting contract tokens max - removes all staked tokens', function () {
cy.staking_page_associate_tokens('3', { type: 'contract' });
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list('1');
cy.staking_validator_page_add_stake('2');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
2.0,
txTimeout
);
cy.close_staking_dialog();
cy.staking_page_disassociate_all_tokens('contract');
cy.get(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, txTimeout).should('not.exist');
});
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('0.0', txTimeout)
.should('be.visible');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.00'
);
});
cy.get(vegaWalletStakedBalances, txTimeout).should(
'not.exist',
txTimeout
);
cy.navigate_to('validators');
cy.validate_validator_list_total_stake_and_share('0', '0.00', '0.00%');
});
it('Disassociating some tokens - prioritizes unstaked tokens', function () {
cy.staking_page_associate_tokens('3');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('2');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
2.0,
txTimeout
);
cy.close_staking_dialog();
cy.staking_page_disassociate_tokens('1');
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('2.0', txTimeout)
.should('be.visible');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'2.00'
);
});
cy.get(vegaWalletStakedBalances, txTimeout)
.should('contain', 2.0, txTimeout)
.and('contain', partValidatorId);
cy.navigate_to('validators');
cy.validate_validator_list_total_stake_and_share(
'0',
'2.00',
'100.00%'
);
});
it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
// 2001-STKE-004
cy.staking_page_associate_tokens('3');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('3');
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.close_staking_dialog();
cy.staking_page_associate_tokens('4');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
0.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
7.0,
txTimeout
);
});
it('Associating vesting contract tokens - when some already staked - auto stakes tokens to staked validator', function () {
// 2001-STKE-004
cy.staking_page_associate_tokens('3', { type: 'contract' });
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('3');
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.close_staking_dialog();
cy.staking_page_associate_tokens('4', { type: 'contract' });
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
0.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
7.0,
txTimeout
);
});
it('Associating vesting contract tokens - when wallet tokens already staked - auto stakes tokens to staked validator', function () {
// 2001-STKE-004
cy.staking_page_associate_tokens('3', { type: 'wallet' });
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('3');
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.close_staking_dialog();
cy.staking_page_associate_tokens('4', { type: 'contract' });
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
0.0,
txTimeout
);
cy.get(vegaWalletStakedBalances, txTimeout).should(
'contain',
7.0,
txTimeout
);
});
it('Associating tokens - with multiple validators already staked - auto stakes to staked validators - abiding by existing stake ratio', function () {
// 2001-STKE-004
cy.staking_page_associate_tokens('6');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
6.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('2');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
0.0,
txTimeout
);
cy.close_staking_dialog();
cy.click_on_validator_from_list(1);
cy.staking_validator_page_add_stake('4');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
0.0,
txTimeout
);
cy.close_staking_dialog();
cy.staking_page_associate_tokens('6');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'12.00'
);
});
cy.get(vegaWalletStakedBalances, txTimeout)
.should('contain', '4.0', txTimeout)
.and('contain', partValidatorId);
cy.get(vegaWalletStakedBalances, txTimeout)
.should('contain', '8.0')
.and('contain', partValidatorId);
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
0.0,
txTimeout
);
});
it('Selecting use maximum where tokens are already staked - suggests the unstaked token amount', function () {
cy.staking_page_associate_tokens('3');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
3.0,
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('2');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
1.0,
txTimeout
);
cy.close_staking_dialog();
cy.click_on_validator_from_list(0);
cy.get(stakeAddStakeRadioButton).click();
cy.get(stakeMaximumTokens, { timeout: 60000 }).click();
cy.get(stakeTokenSubmitButton).should('contain', 'Add 1 $VEGA tokens');
});
after('teardown wallet', function () {
cy.vega_wallet_teardown();
});
});
}
);

View File

@ -0,0 +1,454 @@
/// <reference types="cypress" />
import {
verifyUnstakedBalance,
verifyStakedBalance,
verifyEthWalletTotalAssociatedBalance,
verifyEthWalletAssociatedBalance,
waitForSpinner,
navigateTo,
navigation,
} from '../../support/common.functions';
import {
clickOnValidatorFromList,
closeStakingDialog,
ensureSpecifiedUnstakedTokensAreAssociated,
stakingPageAssociateTokens,
stakingPageDisassociateAllTokens,
stakingPageDisassociateTokens,
stakingValidatorPageAddStake,
stakingValidatorPageRemoveStake,
validateValidatorListTotalStakeAndShare,
waitForBeginningOfEpoch,
} from '../../support/staking.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import {
vegaWalletSetSpecifiedApprovalAmount,
vegaWalletTeardown,
} from '../../support/wallet-teardown.functions';
const stakeValidatorListTotalStake = '[col-id="stake"] > div > span';
const stakeValidatorListTotalShare = '[col-id="stakeShare"] > div > span';
const stakeValidatorListValidatorStake = '[col-id="stake"] > div > span';
const stakeRemoveStakeRadioButton = '[data-testid="remove-stake-radio"]';
const stakeTokenAmountInputBox = '[data-testid="token-amount-input"]';
const stakeTokenSubmitButton = '[data-testid="token-input-submit-button"]';
const stakeAddStakeRadioButton = '[data-testid="add-stake-radio"]';
const stakeMaximumTokens = '[data-testid="token-amount-use-maximum"]';
const totalStake = '[data-testid="total-stake"]';
const stakeShare = '[data-testid="stake-percentage"]';
const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort');
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
const vegaWalletStakedBalances =
'[data-testid="vega-wallet-balance-staked-validators"]';
const ethWalletContainer = '[data-testid="ethereum-wallet"]';
const vegaWallet = '[data-testid="vega-wallet"]';
const txTimeout = Cypress.env('txTimeout');
const epochTimeout = Cypress.env('epochTimeout');
context(
'Staking Tab - with eth and vega wallets connected',
{ tags: '@slow' },
function () {
// 2001-STKE-002, 2001-STKE-032
before('visit staking tab and connect vega wallet', function () {
cy.visit('/');
ethereumWalletConnect();
// this is a workaround for #2422 which can be removed once issue is resolved
cy.associateTokensToVegaWallet('4');
vegaWalletSetSpecifiedApprovalAmount('1000');
});
describe('Eth wallet - contains VEGA tokens', function () {
beforeEach(
'teardown wallet & drill into a specific validator',
function () {
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
ethereumWalletConnect();
navigateTo(navigation.validators);
}
);
it('Able to stake against a validator - using vega from wallet', function () {
ensureSpecifiedUnstakedTokensAreAssociated('3');
verifyUnstakedBalance(3.0);
verifyEthWalletTotalAssociatedBalance('3.0');
verifyEthWalletAssociatedBalance('3.0');
cy.get('button').contains('Select a validator to nominate').click();
// 2001-STKE-031
clickOnValidatorFromList(0);
// 2001-STKE-033, 2001-STKE-034, 2001-STKE-037
stakingValidatorPageAddStake('2');
verifyUnstakedBalance(1.0);
// 2001-STKE-039
verifyStakedBalance(2.0);
verifyNextEpochValue(2.0); // 2001-STKE-016 2001-STKE-038
verifyThisEpochValue(2.0); // 2001-STKE-013
closeStakingDialog();
navigateTo(navigation.validators);
// 2002-SINC-007
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
});
it('Able to stake against a validator - using vega from vesting contract', function () {
stakingPageAssociateTokens('3', { type: 'contract' });
verifyUnstakedBalance(3.0);
verifyEthWalletTotalAssociatedBalance('3.0');
verifyEthWalletAssociatedBalance('3.0');
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('2');
verifyUnstakedBalance(1.0);
verifyStakedBalance(2.0);
verifyNextEpochValue(2.0);
verifyThisEpochValue(2.0);
closeStakingDialog();
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
});
it('Able to stake against a validator - using vega from both wallet and vesting contract', function () {
stakingPageAssociateTokens('3', { type: 'contract' });
navigateTo(navigation.validators);
stakingPageAssociateTokens('4', { type: 'wallet' });
verifyUnstakedBalance(7.0);
verifyEthWalletTotalAssociatedBalance('3.0');
verifyEthWalletTotalAssociatedBalance('4.0');
verifyEthWalletTotalAssociatedBalance('3.0');
verifyEthWalletTotalAssociatedBalance('4.0');
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('6');
verifyUnstakedBalance(1.0);
verifyStakedBalance(6.0);
verifyNextEpochValue(6.0);
verifyThisEpochValue(6.0);
closeStakingDialog();
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '6.00', '100.00%');
});
it('Able to stake against multiple validators', function () {
stakingPageAssociateTokens('5');
verifyUnstakedBalance(5.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('2');
verifyUnstakedBalance(3.0);
cy.get(vegaWalletStakedBalances, txTimeout)
.parent()
.should('contain', 2.0, txTimeout);
closeStakingDialog();
navigateTo(navigation.validators);
clickOnValidatorFromList(1);
stakingValidatorPageAddStake('1');
verifyUnstakedBalance(2.0);
cy.get(vegaWalletStakedBalances, txTimeout)
.should('have.length', 4, txTimeout)
.eq(0)
.should('contain', 2.0, txTimeout);
cy.get(vegaWalletStakedBalances, txTimeout)
.eq(1)
.should('contain', 1.0, txTimeout);
closeStakingDialog();
navigateTo(navigation.validators);
cy.get(`[row-id="${0}"]`).within(() => {
cy.get(stakeValidatorListTotalStake)
.should('have.text', '2.00')
.and('be.visible');
cy.get(stakeValidatorListTotalShare)
.should('have.text', '66.67%')
.and('be.visible');
cy.get(stakeValidatorListValidatorStake)
.scrollIntoView()
.should('have.text', '2.00')
.and('be.visible');
});
cy.get(`[row-id="${1}"]`).within(() => {
cy.get(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '1.00')
.and('be.visible');
cy.get(stakeValidatorListTotalShare)
.should('have.text', '33.33%')
.and('be.visible');
cy.get(stakeValidatorListValidatorStake)
.scrollIntoView()
.should('have.text', '1.00')
.and('be.visible');
});
});
// 2001-STKE-041
it(
'Able to remove part of a stake against a validator',
{ tags: '@smoke' },
function () {
ensureSpecifiedUnstakedTokensAreAssociated('4');
navigateTo(navigation.validators);
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('3');
verifyNextEpochValue(3.0);
verifyUnstakedBalance(1.0);
closeStakingDialog();
navigateTo(navigation.validators);
// 2001-STKE-040
clickOnValidatorFromList(0);
// 2001-STKE-044, 2001-STKE-048
stakingValidatorPageRemoveStake('1');
// 2001-STKE-049
verifyNextEpochValue(2.0);
verifyUnstakedBalance(2.0);
verifyStakedBalance(2.0);
verifyNextEpochValue(2.0);
verifyThisEpochValue(2.0);
cy.get(totalStake, epochTimeout).should('contain.text', '2');
waitForBeginningOfEpoch();
cy.get(stakeShare).should('have.text', '100%');
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
}
);
// 2001-STKE-045
it('Able to remove a full stake against a validator', function () {
stakingPageAssociateTokens('3');
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('1');
verifyUnstakedBalance(2.0);
closeStakingDialog();
navigateTo(navigation.validators);
clickOnValidatorFromList(0);
stakingValidatorPageRemoveStake('1');
verifyNextEpochValue(0.0);
verifyUnstakedBalance(3.0);
verifyNextEpochValue(0.0);
verifyThisEpochValue(0.0);
cy.get(vegaWalletStakedBalances, txTimeout).should(
'not.exist',
txTimeout
);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
});
it('Unable to remove a stake with a negative value for a validator', function () {
stakingPageAssociateTokens('3');
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('2');
verifyNextEpochValue(2.0);
verifyUnstakedBalance(1.0);
closeStakingDialog();
navigateTo(navigation.validators);
clickOnValidatorFromList(0);
cy.get(stakeRemoveStakeRadioButton, txTimeout).click();
cy.get(stakeTokenAmountInputBox).type('-0.1');
cy.contains('Waiting for next epoch to start', epochTimeout);
cy.get(stakeTokenSubmitButton)
.should('be.disabled', epochTimeout)
.and('contain', `Remove -0.1 $VEGA tokens at the end of epoch`)
.and('be.visible');
});
it('Unable to remove a stake greater than staked amount next epoch for a validator', function () {
stakingPageAssociateTokens('3');
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('2');
verifyNextEpochValue(2.0);
verifyUnstakedBalance(3.0);
closeStakingDialog();
navigateTo(navigation.validators);
clickOnValidatorFromList(0);
cy.get(stakeRemoveStakeRadioButton).click();
cy.get(stakeTokenAmountInputBox).type('4');
cy.contains('Waiting for next epoch to start', epochTimeout);
cy.get(stakeTokenSubmitButton)
.should('be.disabled', epochTimeout)
.and('contain', `Remove 4 $VEGA tokens at the end of epoch`)
.and('be.visible');
});
it('Disassociating all wallet tokens max - removes all staked tokens', function () {
stakingPageAssociateTokens('3');
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(1);
stakingValidatorPageAddStake('2');
verifyUnstakedBalance(3.0);
verifyStakedBalance(2.0);
closeStakingDialog();
stakingPageDisassociateAllTokens();
cy.get(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, txTimeout).should('not.exist');
});
verifyEthWalletTotalAssociatedBalance('0.0');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.00'
);
});
cy.get(vegaWalletStakedBalances, txTimeout).should(
'not.exist',
txTimeout
);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
});
it('Disassociating all vesting contract tokens max - removes all staked tokens', function () {
stakingPageAssociateTokens('3', { type: 'contract' });
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(1);
stakingValidatorPageAddStake('2');
verifyUnstakedBalance(1.0);
verifyStakedBalance(2.0);
closeStakingDialog();
stakingPageDisassociateAllTokens('contract');
cy.get(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, txTimeout).should('not.exist');
});
verifyEthWalletTotalAssociatedBalance('0.0');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.00'
);
});
cy.get(vegaWalletStakedBalances, txTimeout).should(
'not.exist',
txTimeout
);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
});
it('Disassociating some tokens - prioritizes unstaked tokens', function () {
stakingPageAssociateTokens('3');
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('2');
verifyUnstakedBalance(1.0);
verifyStakedBalance(2.0);
closeStakingDialog();
stakingPageDisassociateTokens('1');
verifyEthWalletTotalAssociatedBalance('2.0');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'2.00'
);
});
verifyStakedBalance(2.0);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
});
it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
// 2001-STKE-004
stakingPageAssociateTokens('3');
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('3');
verifyStakedBalance(3.0);
closeStakingDialog();
stakingPageAssociateTokens('4');
verifyUnstakedBalance(0.0);
verifyStakedBalance(7.0);
});
it('Associating vesting contract tokens - when some already staked - auto stakes tokens to staked validator', function () {
// 2001-STKE-004
stakingPageAssociateTokens('3', { type: 'contract' });
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('3');
verifyStakedBalance(3.0);
closeStakingDialog();
stakingPageAssociateTokens('4', { type: 'contract' });
verifyUnstakedBalance(0.0);
verifyStakedBalance(7.0);
});
it('Associating vesting contract tokens - when wallet tokens already staked - auto stakes tokens to staked validator', function () {
// 2001-STKE-004
stakingPageAssociateTokens('3', { type: 'wallet' });
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('3');
verifyStakedBalance(3.0);
closeStakingDialog();
stakingPageAssociateTokens('4', { type: 'contract' });
verifyUnstakedBalance(0.0);
verifyStakedBalance(7.0);
});
it('Associating tokens - with multiple validators already staked - auto stakes to staked validators - abiding by existing stake ratio', function () {
// 2001-STKE-004
stakingPageAssociateTokens('6');
verifyUnstakedBalance(6.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('2');
verifyUnstakedBalance(0.0);
closeStakingDialog();
clickOnValidatorFromList(1);
stakingValidatorPageAddStake('4');
verifyUnstakedBalance(0.0);
closeStakingDialog();
stakingPageAssociateTokens('6');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'12.00'
);
});
verifyStakedBalance(4.0);
verifyStakedBalance(8.0);
verifyUnstakedBalance(0.0);
});
it('Selecting use maximum where tokens are already staked - suggests the unstaked token amount', function () {
stakingPageAssociateTokens('3');
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('2');
verifyUnstakedBalance(1.0);
closeStakingDialog();
clickOnValidatorFromList(0);
cy.get(stakeAddStakeRadioButton).click();
cy.get(stakeMaximumTokens, { timeout: 60000 }).click();
cy.get(stakeTokenSubmitButton).should('contain', 'Add 1 $VEGA tokens');
});
afterEach('Teardown Wallet', function () {
vegaWalletTeardown();
});
function verifyNextEpochValue(amount: number) {
cy.getByTestId('stake-next-epoch', epochTimeout)
.contains(amount, epochTimeout)
.should('be.visible');
}
function verifyThisEpochValue(amount: number) {
cy.getByTestId('stake-this-epoch', epochTimeout) // 2001-STKE-013
.contains(amount, epochTimeout)
.should('be.visible');
}
});
}
);

View File

@ -1,13 +1,31 @@
import {
verifyEthWalletTotalAssociatedBalance,
verifyEthWalletAssociatedBalance,
waitForSpinner,
navigateTo,
navigation,
} from '../../support/common.functions';
import {
stakingPageAssociateTokens,
stakingPageDisassociateAllTokens,
stakingPageDisassociateTokens,
validateWalletCurrency,
} from '../../support/staking.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import {
vegaWalletAssociate,
vegaWalletDisassociate,
vegaWalletSetSpecifiedApprovalAmount,
vegaWalletTeardown,
} from '../../support/wallet-teardown.functions';
const ethWalletContainer = '[data-testid="ethereum-wallet"]'; const ethWalletContainer = '[data-testid="ethereum-wallet"]';
const ethWalletAssociatedBalances =
'[data-testid="eth-wallet-associated-balances"]';
const ethWalletTotalAssociatedBalance = '[data-testid="currency-locked"]';
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]'; const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
const vegaWalletUnstakedBalance = const vegaWalletUnstakedBalance =
'[data-testid="vega-wallet-balance-unstaked"]'; '[data-testid="vega-wallet-balance-unstaked"]';
const txTimeout = Cypress.env('txTimeout'); const txTimeout = Cypress.env('txTimeout');
const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort'); const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort');
const ethWalletAssociateButton = '[href="/token/associate"]'; const ethWalletAssociateButton = '[data-testid="associate-btn"]';
const associateWalletRadioButton = '[data-testid="associate-radio-wallet"]'; const associateWalletRadioButton = '[data-testid="associate-radio-wallet"]';
const tokenAmountInputBox = '[data-testid="token-amount-input"]'; const tokenAmountInputBox = '[data-testid="token-amount-input"]';
const tokenSubmitButton = '[data-testid="token-input-submit-button"]'; const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
@ -28,7 +46,7 @@ context(
before('visit staking tab and connect vega wallet', function () { before('visit staking tab and connect vega wallet', function () {
cy.visit('/'); cy.visit('/');
// 0005-ETXN-001 // 0005-ETXN-001
cy.vega_wallet_set_specified_approval_amount('1000'); vegaWalletSetSpecifiedApprovalAmount('1000');
}); });
describe('Eth wallet - contains VEGA tokens', function () { describe('Eth wallet - contains VEGA tokens', function () {
@ -36,11 +54,10 @@ context(
'teardown wallet & drill into a specific validator', 'teardown wallet & drill into a specific validator',
function () { function () {
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.ethereum_wallet_connect();
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.vega_wallet_teardown(); ethereumWalletConnect();
cy.navigate_to('validators'); vegaWalletTeardown();
} }
); );
@ -57,26 +74,21 @@ context(
//0005-ETXN-006 //0005-ETXN-006
//0005-ETXN-003 //0005-ETXN-003
//0005-ETXN-005 //0005-ETXN-005
cy.staking_page_associate_tokens('2', { skipConfirmation: true }); stakingPageAssociateTokens('2', { skipConfirmation: true });
cy.getByTestId('currency-title', txTimeout).should( cy.getByTestId('currency-title', txTimeout).should(
'have.length.above', 'have.length.above',
3 3
); );
cy.validate_wallet_currency('Associated', '0.00'); validateWalletCurrency('Associated', '0.00');
cy.validate_wallet_currency('Pending association', '2.00'); validateWalletCurrency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '2.00'); validateWalletCurrency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3); cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
// 0005-ETXN-002 // 0005-ETXN-002
cy.get(ethWalletAssociatedBalances, txTimeout) verifyEthWalletAssociatedBalance('2.0');
.contains(vegaWalletPublicKeyShort)
.parent(txTimeout)
.should('contain', 2.0);
cy.get(ethWalletTotalAssociatedBalance, txTimeout) verifyEthWalletTotalAssociatedBalance('2.0');
.contains('2.0', txTimeout)
.should('be.visible');
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
@ -92,50 +104,30 @@ context(
// 1004-ASSO-029 // 1004-ASSO-029
// 1004-ASSO-031 // 1004-ASSO-031
cy.staking_page_associate_tokens('2'); stakingPageAssociateTokens('2');
verifyEthWalletAssociatedBalance('2.0');
cy.get(ethWalletAssociatedBalances, txTimeout) verifyEthWalletTotalAssociatedBalance('2.0');
.contains(vegaWalletPublicKeyShort)
.parent(txTimeout)
.should('contain', 2.0);
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('2.0', txTimeout)
.should('be.visible');
cy.get('button').contains('Select a validator to nominate').click(); cy.get('button').contains('Select a validator to nominate').click();
stakingPageDisassociateTokens('2');
cy.staking_page_disassociate_tokens('2');
cy.getByTestId('currency-title', txTimeout).should( cy.getByTestId('currency-title', txTimeout).should(
'have.length.above', 'have.length.above',
3 3
); );
cy.validate_wallet_currency('Associated', '2.00'); validateWalletCurrency('Associated', '2.00');
cy.validate_wallet_currency('Pending association', '2.00'); validateWalletCurrency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '0.00'); validateWalletCurrency('Total associated after pending', '0.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3); cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.getByTestId('eth-wallet-associated-balances', txTimeout).should(
cy.get(ethWalletAssociatedBalances, txTimeout).should('not.exist'); 'not.exist'
);
cy.get(ethWalletTotalAssociatedBalance, txTimeout) verifyEthWalletTotalAssociatedBalance('0.00');
.contains('0.00', txTimeout)
.should('be.visible');
}); });
it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () { it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () {
//1004-ASSO-011 //1004-ASSO-011
cy.staking_page_associate_tokens('1001', { approve: true }); stakingPageAssociateTokens('1001', { approve: true });
verifyEthWalletAssociatedBalance('1,001.00');
cy.get(ethWalletAssociatedBalances, txTimeout) verifyEthWalletTotalAssociatedBalance('1,001.00');
.contains(vegaWalletPublicKeyShort)
.parent()
.should('contain', '1,001.00', txTimeout);
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('1,001.00', txTimeout)
.should('be.visible');
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should( cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain', 'contain',
@ -145,26 +137,14 @@ context(
}); });
it('Able to disassociate a partial amount of tokens currently associated', function () { it('Able to disassociate a partial amount of tokens currently associated', function () {
cy.staking_page_associate_tokens('2'); stakingPageAssociateTokens('2');
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
}); });
cy.get('button').contains('Select a validator to nominate').click(); cy.get('button').contains('Select a validator to nominate').click();
stakingPageDisassociateTokens('1');
cy.staking_page_disassociate_tokens('1'); verifyEthWalletAssociatedBalance('1.0');
cy.get(ethWalletAssociatedBalances, txTimeout)
.contains(vegaWalletPublicKeyShort)
.parent(txTimeout)
.should('contain', 1.0);
cy.get(ethWalletAssociatedBalances, txTimeout)
.contains(vegaWalletPublicKeyShort)
.parent(txTimeout)
.should('contain', 1.0);
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 1.0); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 1.0);
}); });
@ -174,32 +154,24 @@ context(
// 1004-ASSO-026 // 1004-ASSO-026
const warningText = const warningText =
'Warning: Any tokens that have been nominated to a node will sacrifice rewards they are due for the current epoch. If you do not wish to sacrifice these, you should remove stake from a node at the end of an epoch before disassociation.'; 'Warning: Any tokens that have been nominated to a node will sacrifice rewards they are due for the current epoch. If you do not wish to sacrifice these, you should remove stake from a node at the end of an epoch before disassociation.';
stakingPageAssociateTokens('2');
cy.staking_page_associate_tokens('2');
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
}); });
cy.get('button').contains('Select a validator to nominate').click(); cy.get('button').contains('Select a validator to nominate').click();
cy.get(ethWalletDissociateButton).click(); cy.get(ethWalletDissociateButton).click();
cy.get(disassociationWarning).should('contain', warningText); cy.get(disassociationWarning).should('contain', warningText);
stakingPageDisassociateAllTokens();
cy.staking_page_disassociate_all_tokens();
cy.get(ethWalletContainer).within(() => { cy.get(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, { timeout: 20000 }).should( cy.contains(vegaWalletPublicKeyShort, { timeout: 20000 }).should(
'not.exist' 'not.exist'
); );
}); });
cy.get(ethWalletContainer).within(() => { cy.get(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, { timeout: 20000 }).should( cy.contains(vegaWalletPublicKeyShort, { timeout: 20000 }).should(
'not.exist' 'not.exist'
); );
}); });
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 0.0); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 0.0);
}); });
@ -212,7 +184,7 @@ context(
// 1004-ASSO-024 // 1004-ASSO-024
// 1004-ASSO-023 // 1004-ASSO-023
cy.staking_page_associate_tokens('2', { stakingPageAssociateTokens('2', {
type: 'contract', type: 'contract',
skipConfirmation: true, skipConfirmation: true,
}); });
@ -221,47 +193,30 @@ context(
'have.length.above', 'have.length.above',
3 3
); );
cy.validate_wallet_currency('Associated', '0.00'); validateWalletCurrency('Associated', '0.00');
cy.validate_wallet_currency('Pending association', '2.00'); validateWalletCurrency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '2.00'); validateWalletCurrency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3); cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
verifyEthWalletAssociatedBalance('2.0');
cy.get(ethWalletAssociatedBalances, txTimeout) verifyEthWalletTotalAssociatedBalance('2.0');
.contains(vegaWalletPublicKeyShort)
.parent(txTimeout)
.should('contain', 2.0);
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('2.0', txTimeout)
.should('be.visible');
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
}); });
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0); cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
cy.staking_page_disassociate_tokens('1', { stakingPageDisassociateTokens('1', {
type: 'contract', type: 'contract',
skipConfirmation: true, skipConfirmation: true,
}); });
cy.getByTestId('currency-title', txTimeout).should( cy.getByTestId('currency-title', txTimeout).should(
'have.length.above', 'have.length.above',
3 3
); );
cy.validate_wallet_currency('Associated', '2.00'); validateWalletCurrency('Associated', '2.00');
cy.validate_wallet_currency('Pending association', '1.00'); validateWalletCurrency('Pending association', '1.00');
cy.validate_wallet_currency('Total associated after pending', '1.00'); validateWalletCurrency('Total associated after pending', '1.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3); cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
verifyEthWalletAssociatedBalance('1.0');
cy.get(ethWalletAssociatedBalances, txTimeout) verifyEthWalletTotalAssociatedBalance('1.0');
.contains(vegaWalletPublicKeyShort)
.parent(txTimeout)
.should('contain', 1.0);
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
.contains('1.0', txTimeout)
.should('be.visible');
}); });
it('Able to associate & disassociate both wallet and vesting contract tokens', function () { it('Able to associate & disassociate both wallet and vesting contract tokens', function () {
@ -269,11 +224,9 @@ context(
// 1004-ASSO-020 // 1004-ASSO-020
// 1004-ASSO-021 // 1004-ASSO-021
// 1004-ASSO-022 // 1004-ASSO-022
stakingPageAssociateTokens('21', { type: 'wallet' });
cy.staking_page_associate_tokens('21', { type: 'wallet' });
cy.get('button').contains('Select a validator to nominate').click(); cy.get('button').contains('Select a validator to nominate').click();
cy.staking_page_associate_tokens('37', { type: 'contract' }); stakingPageAssociateTokens('37', { type: 'contract' });
cy.get(vestingContractSection).within(() => { cy.get(vestingContractSection).within(() => {
cy.get(associatedKey).should( cy.get(associatedKey).should(
'contain', 'contain',
@ -281,7 +234,6 @@ context(
); );
cy.get(associatedAmount, txTimeout).should('contain', 37); cy.get(associatedAmount, txTimeout).should('contain', 37);
}); });
cy.get(vegaInWalletSection).within(() => { cy.get(vegaInWalletSection).within(() => {
cy.get(associatedKey).should( cy.get(associatedKey).should(
'contain', 'contain',
@ -289,27 +241,21 @@ context(
); );
cy.get(associatedAmount, txTimeout).should('contain', 21); cy.get(associatedAmount, txTimeout).should('contain', 21);
}); });
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 58); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 58);
}); });
stakingPageDisassociateTokens('6', { type: 'contract' });
cy.staking_page_disassociate_tokens('6', { type: 'contract' });
cy.get(vestingContractSection).within(() => { cy.get(vestingContractSection).within(() => {
cy.get(associatedAmount, txTimeout).should('contain', 31); cy.get(associatedAmount, txTimeout).should('contain', 31);
}); });
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 52); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 52);
}); });
navigateTo(navigation.validators);
cy.navigate_to('validators'); stakingPageDisassociateTokens('9', { type: 'wallet' });
cy.staking_page_disassociate_tokens('9', { type: 'wallet' });
cy.get(vegaInWalletSection).within(() => { cy.get(vegaInWalletSection).within(() => {
cy.get(associatedAmount, txTimeout).should('contain', 12); cy.get(associatedAmount, txTimeout).should('contain', 12);
}); });
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 43); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 43);
}); });
@ -319,42 +265,41 @@ context(
// 1004-ASSO-008 // 1004-ASSO-008
// 1004-ASSO-010 // 1004-ASSO-010
// No warning visible as described in AC, but the button is disabled // No warning visible as described in AC, but the button is disabled
cy.get(ethWalletAssociateButton).first().click(); cy.get(ethWalletAssociateButton).first().click();
cy.get(associateWalletRadioButton, { timeout: 30000 }).click(); cy.get(associateWalletRadioButton, { timeout: 30000 }).click();
cy.get(tokenSubmitButton, txTimeout).should('be.disabled'); // button disabled with no input cy.get(tokenSubmitButton, txTimeout).should('be.disabled'); // button disabled with no input
cy.get(tokenAmountInputBox, { timeout: 10000 }).type(6500000); cy.get(tokenAmountInputBox, { timeout: 10000 }).type('6500000');
cy.get(tokenSubmitButton, txTimeout).should('be.disabled'); cy.get(tokenSubmitButton, txTimeout).should('be.disabled');
}); });
// 1004-ASSO-004 // 1004-ASSO-004
it('Pending association outside of app is shown', function () { it('Pending association outside of app is shown', function () {
cy.vega_wallet_associate('2'); vegaWalletAssociate('2');
cy.getByTestId('currency-title', txTimeout).should( cy.getByTestId('currency-title', txTimeout).should(
'have.length.above', 'have.length.above',
3 3
); );
cy.validate_wallet_currency('Associated', '0.00'); validateWalletCurrency('Associated', '0.00');
cy.validate_wallet_currency('Pending association', '2.00'); validateWalletCurrency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '2.00'); validateWalletCurrency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3); cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.validate_wallet_currency('Associated', '2.00'); validateWalletCurrency('Associated', '2.00');
}); });
it('Disassociation outside of app is shown', function () { it('Disassociation outside of app is shown', function () {
cy.staking_page_associate_tokens('2'); stakingPageAssociateTokens('2');
cy.validate_wallet_currency('Associated', '2.00'); cy.wrap(validateWalletCurrency('Associated', '2.00')).then(() => {
cy.vega_wallet_disassociate('2'); vegaWalletDisassociate('2');
});
cy.getByTestId('currency-title', txTimeout).should( cy.getByTestId('currency-title', txTimeout).should(
'have.length.above', 'have.length.above',
3 3
); );
cy.validate_wallet_currency('Associated', '2.00'); validateWalletCurrency('Associated', '2.00');
cy.validate_wallet_currency('Pending association', '2.00'); validateWalletCurrency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '0.00'); validateWalletCurrency('Total associated after pending', '0.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3); cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.validate_wallet_currency('Associated', '0.00'); validateWalletCurrency('Associated', '0.00');
}); });
it('Able to associate tokens to different public key of connected vega wallet', function () { it('Able to associate tokens to different public key of connected vega wallet', function () {
@ -371,7 +316,7 @@ context(
'have.text', 'have.text',
Cypress.env('vegaWalletPublicKey2') Cypress.env('vegaWalletPublicKey2')
); );
cy.staking_page_associate_tokens('2'); stakingPageAssociateTokens('2');
cy.get(vegaWallet).within(() => { cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0); cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
}); });
@ -381,7 +326,7 @@ context(
'vegaWalletPublicKey2Short' 'vegaWalletPublicKey2Short'
)} can now participate in governance and nominate a validator with your associated $VEGA.` )} can now participate in governance and nominate a validator with your associated $VEGA.`
); );
cy.staking_page_disassociate_all_tokens(); stakingPageDisassociateAllTokens();
}); });
}); });
} }

View File

@ -1,5 +1,16 @@
import {
navigateTo,
navigation,
waitForSpinner,
} from '../../support/common.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import {
depositAsset,
vegaWalletTeardown,
} from '../../support/wallet-teardown.functions';
const withdraw = 'withdraw'; const withdraw = 'withdraw';
const selectAsset = 'select-asset'; const withdrawalForm = 'withdraw-form';
const ethAddressInput = 'eth-address-input'; const ethAddressInput = 'eth-address-input';
const amountInput = 'amount-input'; const amountInput = 'amount-input';
const balanceAvailable = 'BALANCE_AVAILABLE_value'; const balanceAvailable = 'BALANCE_AVAILABLE_value';
@ -17,6 +28,8 @@ const completeWithdrawalButton = 'complete-withdrawal';
const usdtName = 'USDC (local)'; const usdtName = 'USDC (local)';
const usdcEthAddress = '0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0'; const usdcEthAddress = '0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0';
const usdcSymbol = 'tUSDC'; const usdcSymbol = 'tUSDC';
const usdtSelectValue =
'993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede';
const truncatedWithdrawalEthAddress = '0xEe7D…22d94F'; const truncatedWithdrawalEthAddress = '0xEe7D…22d94F';
const formValidationError = 'input-error-text'; const formValidationError = 'input-error-text';
const txTimeout = Cypress.env('txTimeout'); const txTimeout = Cypress.env('txTimeout');
@ -26,60 +39,72 @@ context(
{ tags: '@slow' }, { tags: '@slow' },
function () { function () {
before('visit withdrawals and connect vega wallet', function () { before('visit withdrawals and connect vega wallet', function () {
cy.updateCapsuleMultiSig(); // When running tests locally, will fail if run without restarting capsule cy.visit('/');
cy.deposit_asset(usdcEthAddress, '100000000000000000000'); // When running tests locally, will fail if run without restarting capsule
cy.updateCapsuleMultiSig().then(() => {
depositAsset(usdcEthAddress, '100');
});
}); });
beforeEach('Navigate to withdrawal page', function () { beforeEach('Navigate to withdrawal page', function () {
cy.reload(); cy.reload();
cy.visit('/'); waitForSpinner();
cy.wait_for_spinner(); navigateTo(navigation.withdraw);
cy.navigate_to('withdraw');
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.ethereum_wallet_connect(); ethereumWalletConnect();
cy.vega_wallet_teardown(); vegaWalletTeardown();
}); });
it('Able to open withdrawal form with vega wallet connected', function () { it('Able to open withdrawal form with vega wallet connected', function () {
// needs to reload page for withdrawal form to be displayed in ci - not reproducible outside of ci // needs to reload page for withdrawal form to be displayed in ci - not reproducible outside of ci
cy.reload();
waitForSpinner();
ethereumWalletConnect();
cy.getByTestId(withdraw).should('be.visible').click(); cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(selectAsset) cy.getByTestId(withdrawalForm).within(() => {
.find('option') cy.get('select').find('option').should('have.length.at.least', 2);
.should('have.length.at.least', 2); cy.getByTestId(ethAddressInput).should('be.visible');
cy.getByTestId(ethAddressInput).should('be.visible'); cy.getByTestId(amountInput).should('be.visible');
cy.getByTestId(amountInput).should('be.visible'); });
}); });
it('Unable to submit withdrawal with invalid fields', function () { it('Unable to submit withdrawal with invalid fields', function () {
cy.getByTestId(withdraw).should('be.visible').click(); cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(selectAsset).select(usdtName); cy.getByTestId(withdrawalForm).within(() => {
cy.getByTestId(balanceAvailable, txTimeout).should('exist'); cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(submitWithdrawalButton).click(); cy.getByTestId(balanceAvailable, txTimeout).should('exist');
cy.getByTestId(formValidationError).should('have.length', 1); cy.getByTestId(submitWithdrawalButton).click();
cy.getByTestId(amountInput).clear().click().type('0.0000001'); cy.getByTestId(formValidationError).should('have.length', 1);
cy.getByTestId(submitWithdrawalButton).click(); cy.getByTestId(amountInput).clear().click().type('0.0000001');
cy.getByTestId(formValidationError).should( cy.getByTestId(submitWithdrawalButton).click();
'have.text', cy.getByTestId(formValidationError).should(
'Value is below minimum' 'have.text',
); 'Value is below minimum'
cy.getByTestId(amountInput).clear().click().type('10'); );
cy.getByTestId(ethAddressInput).click().type('123'); cy.getByTestId(amountInput).clear().click().type('10');
cy.getByTestId(submitWithdrawalButton).click(); cy.getByTestId(ethAddressInput).click().type('123');
cy.getByTestId(formValidationError).should( cy.getByTestId(submitWithdrawalButton).click();
'have.text', cy.getByTestId(formValidationError).should(
'Invalid Ethereum address' 'have.text',
); 'Invalid Ethereum address'
);
});
}); });
it('Able to withdraw asset: -eth wallet connected -withdraw funds button', function () { it('Able to withdraw asset: -eth wallet connected -withdraw funds button', function () {
// fill in withdrawal form // fill in withdrawal form
cy.getByTestId(withdraw).should('be.visible').click(); cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(selectAsset).select(usdtName); cy.getByTestId(withdrawalForm).within(() => {
cy.getByTestId(balanceAvailable, txTimeout).should('exist'); cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(withdrawalThreshold).should('have.text', '100,000.00000T'); cy.getByTestId(balanceAvailable, txTimeout).should('exist');
cy.getByTestId(delayTime).should('have.text', 'None'); cy.getByTestId(withdrawalThreshold).should(
cy.getByTestId(amountInput).click().type('100'); 'have.text',
cy.getByTestId(submitWithdrawalButton).click(); '100,000.00000T'
);
cy.getByTestId(delayTime).should('have.text', 'None');
cy.getByTestId(amountInput).click().type('100');
cy.getByTestId(submitWithdrawalButton).click();
});
cy.contains('Awaiting network confirmation').should('be.visible'); cy.contains('Awaiting network confirmation').should('be.visible');
// assert withdrawal request // assert withdrawal request
@ -136,15 +161,17 @@ context(
waitForAssetsDisplayed(usdtName); waitForAssetsDisplayed(usdtName);
// fill in withdrawal form // fill in withdrawal form
cy.getByTestId(withdraw).should('be.visible').click(); cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(selectAsset).select(usdtName); cy.getByTestId(withdrawalForm).within(() => {
cy.getByTestId(ethAddressInput).should('be.empty'); cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(amountInput).click().type('100'); cy.getByTestId(ethAddressInput).should('be.empty');
cy.getByTestId(submitWithdrawalButton).click(); cy.getByTestId(amountInput).click().type('100');
cy.getByTestId(submitWithdrawalButton).click();
// Need eth address to submit withdrawal // Need eth address to submit withdrawal
cy.getByTestId(formValidationError).should('have.length', 1); cy.getByTestId(formValidationError).should('have.length', 1);
cy.getByTestId(ethAddressInput).click().type(ethWalletAddress); cy.getByTestId(ethAddressInput).click().type(ethWalletAddress);
cy.getByTestId(submitWithdrawalButton).click(); cy.getByTestId(submitWithdrawalButton).click();
});
cy.contains('Awaiting network confirmation').should('be.visible'); cy.contains('Awaiting network confirmation').should('be.visible');
// assert withdrawal request // assert withdrawal request
@ -180,10 +207,12 @@ context(
cy.connectPublicKey(vegaWalletPubKey); cy.connectPublicKey(vegaWalletPubKey);
cy.getByTestId(withdraw).should('be.visible').click(); cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(selectAsset).select(usdtName); cy.getByTestId(withdrawalForm).within(() => {
cy.getByTestId(balanceAvailable, txTimeout).should('exist'); cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(amountInput).click().type('100'); cy.getByTestId(balanceAvailable, txTimeout).should('exist');
cy.getByTestId(submitWithdrawalButton).click(); cy.getByTestId(amountInput).click().type('100');
cy.getByTestId(submitWithdrawalButton).click();
});
cy.getByTestId('dialog-content').within(() => { cy.getByTestId('dialog-content').within(() => {
cy.get('h1').should('have.text', 'Transaction failed'); cy.get('h1').should('have.text', 'Transaction failed');
@ -191,7 +220,7 @@ context(
}); });
}); });
function waitForAssetsDisplayed(expectedAsset) { function waitForAssetsDisplayed(expectedAsset: string) {
cy.contains(expectedAsset, txTimeout).should('be.visible'); cy.contains(expectedAsset, txTimeout).should('be.visible');
} }
} }

View File

@ -1,3 +1,5 @@
import { waitForSpinner } from '../../support/common.functions';
context('Home Page - verify elements on page', { tags: '@smoke' }, function () { context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
before('visit token home page', function () { before('visit token home page', function () {
cy.visit('/'); cy.visit('/');
@ -18,7 +20,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
if (!$body.find('[data-testid="proposals-list-item"]').length) { if (!$body.find('[data-testid="proposals-list-item"]').length) {
cy.createMarket(); cy.createMarket();
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
} }
}); });
cy.getByTestId('proposals-list-item') cy.getByTestId('proposals-list-item')
@ -107,5 +109,56 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
}); });
}); });
}); });
describe('Mobile view - navigation bar', function () {
before('Change to mobile resolution', function () {
cy.viewport('iphone-xr');
});
it('should have burger button', () => {
cy.getByTestId('button-menu-drawer').should('be.visible').click();
cy.getByTestId('menu-drawer').should('be.visible');
});
it('should have link for proposal page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/proposals"]')
.should('exist')
.and('have.text', 'Proposals');
});
});
it('should have link for validator page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/validators"]')
.first()
.should('exist')
.and('have.text', 'Validators');
});
});
it('should have link for rewards page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/rewards"]')
.first()
.should('exist')
.and('have.text', 'Rewards');
});
});
it('should have link for withdrawal page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/token/withdraw"]')
.first()
.should('exist')
.and('have.text', 'Withdraw');
});
});
after(function () {
cy.viewport(
Cypress.config('viewportWidth'),
Cypress.config('viewportHeight')
);
});
});
}); });
}); });

View File

@ -1,284 +0,0 @@
context(
'Landing pages - verifies required elements',
{ tags: '@smoke' },
() => {
const navbar = 'nav .navbar';
const mobileNav = '[data-testid="menu-drawer"]';
const topLevelLinks = [
{
name: 'Proposals',
selector: '[href="/proposals"]',
tests: () => {
it('should be able to see a working link for - find out more about Vega governance', function () {
const governanceDocsUrl = 'https://vega.xyz/governance';
const proposalDocumentationLink =
'[data-testid="proposal-documentation-link"]';
// 3001-VOTE-001
cy.get(proposalDocumentationLink)
.should('be.visible')
.and('have.text', 'Find out more about Vega governance')
.and('have.attr', 'href')
.and('equal', governanceDocsUrl);
// 3002-PROP-001
cy.request(governanceDocsUrl)
.its('body')
.then((body) => {
if (!body.includes('Govern the network')) {
assert.include(
body,
'Govern the network',
`Checking that governance link destination includes 'Govern the network' text`
);
}
});
});
it('should be able to see button for - new proposal', function () {
// 3001-VOTE-002
const newProposalLink = '[data-testid="new-proposal-link"]';
cy.get(newProposalLink)
.should('be.visible')
.and('have.text', 'New proposal')
.and('have.attr', 'href')
.and('equal', '/proposals/propose');
});
},
},
{
name: 'Validators',
selector: '[href="/validators"]',
tests: () => {
it('Should have Staking Guide link visible', function () {
// 2001-STKE-003
cy.get('[data-testid="staking-guide-link"]')
.should('be.visible')
.and('have.text', 'Read more about staking on Vega')
.and(
'have.attr',
'href',
'https://docs.vega.xyz/mainnet/concepts/vega-chain/#staking-on-vega'
);
});
},
},
{
name: 'Rewards',
selector: '[href="/rewards"]',
header: 'Rewards and fees',
tests: () => {
it('should have epoch warning', () => {
cy.get('[data-testid="callout"]')
.should('be.visible')
.and(
'have.text',
'Rewards are credited less than a minute after the epoch ends.This delay is set by a network parameter'
);
});
it('should have toggle for seeing total vs individual rewards', () => {
cy.get('[data-testid="epoch-reward-view-toggle-total"]').should(
'be.visible'
);
});
},
},
];
const secondLevelLinks = [
{
trigger: true,
name: 'Token',
selector: '[data-testid="state-trigger"]',
},
{
name: 'Token',
selector: '[href="/token"]',
header: 'The $VEGA token',
},
{
name: 'Supply & Vesting',
selector: '[href="/token/tranches"]',
header: 'Vesting tranches',
},
{
name: 'Withdraw',
selector: '[href="/token/withdraw"]',
header: 'Withdrawals',
tests: () => {
it('should have connect Vega wallet button', function () {
cy.get('[data-testid="connect-to-vega-wallet-btn"]')
.should('be.visible')
.and('have.text', 'Connect Vega wallet');
});
},
},
{
name: 'Redeem',
selector: '[href="/token/redeem"]',
header: 'Vesting',
tests: () => {
// 1005-VEST-018
it('should have connect Eth wallet button', function () {
cy.get('[data-testid="connect-to-eth-btn"]')
.should('be.visible')
.and('have.text', 'Connect Ethereum wallet');
});
},
},
{
name: 'Associate',
selector: '[href="/token/associate"]',
header: 'Associate $VEGA tokens with Vega Key',
},
{
name: 'Disassociate',
selector: '[href="/token/disassociate"]',
header: 'Disassociate $VEGA tokens from a Vega key',
},
];
const expand = () => {
const trigger = secondLevelLinks.find((l) => l.trigger).selector;
cy.get(trigger).then((el) => {
if (el.attr('aria-expanded') === 'false') {
el.trigger('click');
}
});
};
const collapse = () => {
const trigger = secondLevelLinks.find((l) => l.trigger).selector;
cy.get(trigger).then((el) => {
if (el.attr('aria-expanded') === 'true') {
el.trigger('click');
}
});
};
const ensureHeader = (text) => {
cy.get('main header h1').should('have.text', text);
};
before(() => {
// goes to HOME
cy.visit('/');
// and waits for it to load
cy.get(navbar, { timeout: 10000 }).should('be.visible');
});
describe('Navigation (desktop)', () => {
for (const { name, selector } of topLevelLinks) {
it(`should have ${name} nav link`, () => {
cy.get(navbar).within(() => {
cy.get(selector).should('be.visible');
cy.get(selector).should('have.text', name);
});
});
}
for (const { name, selector, trigger } of secondLevelLinks) {
it(`should have ${name} ${
trigger ? 'as trigger button' : ''
} second level nav link`, () => {
cy.get(navbar).within(() => {
cy.get(selector).should('be.visible');
cy.get(selector).should('have.text', name);
if (trigger) cy.get(selector).click();
});
});
}
after(() => {
collapse();
});
});
describe('Navigation (mobile)', () => {
beforeEach(() => {
// iphone xr
cy.viewport(414, 896);
});
it('should have burger button', () => {
cy.get('[data-testid="button-menu-drawer"]').should('be.visible');
cy.get('[data-testid="button-menu-drawer"]').click();
cy.get(mobileNav).should('be.visible');
});
for (const { name, selector } of topLevelLinks) {
it(`should have ${name} nav link`, () => {
cy.get(mobileNav).within(() => {
cy.get(selector).should('be.visible');
cy.get(selector).should('have.text', name);
});
});
}
for (const { name, selector, trigger } of secondLevelLinks) {
it(`should have ${name} ${
trigger ? 'as trigger button' : ''
} second level nav link`, () => {
cy.get(mobileNav).within(() => {
cy.get(selector).should('be.visible');
cy.get(selector).should('have.text', name);
});
});
}
after(() => {
cy.get('[data-testid="button-menu-drawer"]').click();
cy.viewport(
Cypress.config('viewportWidth'),
Cypress.config('viewportHeight')
);
});
});
describe('Elements', () => {
for (const { name, selector, header, tests } of topLevelLinks) {
describe(`${name} page`, () => {
it(`navigates to ${name}`, () => {
cy.get(navbar).within(() => {
cy.log(`goes to ${name}`);
cy.get(selector).click();
cy.log(`ensures ${name} is highlighted`);
cy.get(selector).should('have.attr', 'aria-current');
});
});
it('displays header', () => {
ensureHeader(header || name);
});
if (tests) tests.apply(this);
});
}
for (const { name, selector, header, tests } of secondLevelLinks.filter(
(l) => !l.trigger
)) {
describe(`${name} page`, () => {
it(`navigates to ${name}`, () => {
cy.get(navbar).within(() => {
expand();
cy.log(`goes to ${name}`);
cy.get(selector).click();
expand();
cy.log(`ensures ${name} is highlighted`);
cy.get(selector).should('have.attr', 'aria-current');
});
});
it('displays header', () => {
ensureHeader(header || name);
});
if (tests) tests.apply(this);
});
}
after(() => {
collapse();
});
});
}
);

View File

@ -0,0 +1,77 @@
import {
navigateTo,
navigation,
verifyPageHeader,
verifyTabHighlighted,
waitForSpinner,
} from '../../support/common.functions';
const proposalDocumentationLink = '[data-testid="proposal-documentation-link"]';
const newProposalButton = '[data-testid="new-proposal-link"]';
const newProposalLink = '[data-testid="new-proposal-link"]';
const governanceDocsUrl = 'https://vega.xyz/governance';
const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]';
context(
'Governance Page - verify elements on page',
{ tags: '@smoke' },
function () {
before('navigate to governance page', function () {
cy.visit('/');
navigateTo(navigation.proposals);
});
describe('with no network change proposals', function () {
it('should have governance tab highlighted', function () {
verifyTabHighlighted(navigation.proposals);
});
it('should have GOVERNANCE header visible', function () {
verifyPageHeader('Proposals');
});
it('should be able to see a working link for - find out more about Vega governance', function () {
// 3001-VOTE-001
cy.get(proposalDocumentationLink)
.should('be.visible')
.and('have.text', 'Find out more about Vega governance')
.and('have.attr', 'href')
.and('equal', governanceDocsUrl);
// 3002-PROP-001
cy.request(governanceDocsUrl)
.its('body')
.then((body) => {
if (!body.includes('Govern the network')) {
assert.include(
body,
'Govern the network',
`Checking that governance link destination includes 'Govern the network' text`
);
}
});
});
it('should be able to see button for - new proposal', function () {
// 3001-VOTE-002
cy.get(newProposalLink)
.should('be.visible')
.and('have.text', 'New proposal')
.and('have.attr', 'href')
.and('equal', '/proposals/propose');
});
// Skipping this test for now, the new proposal button no longer takes a user directly
// to a proposal form, instead it takes them to a page where they can select a proposal type.
// Keeping this test here for now as it can be repurposed to test the new proposal forms.
it.skip('should be able to see a connect wallet button - if vega wallet disconnected and new proposal button selected', function () {
cy.get(newProposalButton).should('be.visible').click();
cy.get(connectToVegaWalletButton)
.should('be.visible')
.and('have.text', 'Connect Vega wallet');
navigateTo(navigation.proposals);
waitForSpinner();
});
});
}
);

View File

@ -1,29 +1,36 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
import {
navigateTo,
navigation,
waitForSpinner,
} from '../../support/common.functions';
import {
enterUniqueFreeFormProposalBody,
goToMakeNewProposal,
} from '../../support/governance.functions';
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey2'); const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey2');
const vegaPubkeyTruncated = Cypress.env('vegaWalletPublicKey2Short'); const vegaPubkeyTruncated = Cypress.env('vegaWalletPublicKey2Short');
const banner = 'view-banner'; const banner = 'view-banner';
context('View functionality with public key', { tags: '@smoke' }, function () { context('View functionality with public key', { tags: '@smoke' }, function () {
before('send asset to wallet', function () { before('send asset to wallet', function () {
cy.vega_wallet_faucet_assets_without_check( vegaWalletFaucetAssetsWithoutCheck('fUSDC', '1000000', vegaWalletPubKey);
'fUSDC',
'1000000',
vegaWalletPubKey
);
}); });
beforeEach('visit home page', function () { beforeEach('visit home page', function () {
cy.visit('/'); cy.visit('/');
cy.wait_for_spinner(); waitForSpinner();
cy.connectPublicKey(vegaWalletPubKey); cy.connectPublicKey(vegaWalletPubKey);
}); });
it('Able to connect public key via wallet', function () { it('Able to connect public key via wallet', function () {
verifyConnectedToPubKey(); verifyConnectedToPubKey();
cy.getByTestId('currency-title', Cypress.env('epochTimeout')).should( cy.getByTestId('currency-title', { timeout: 10000 })
'contain.text', .should('have.length.at.least', 4)
'USDC (fake)' .and('contain.text', 'USDC (fake)');
);
}); });
it('Able to connect public key using url', function () { it('Able to connect public key using url', function () {
@ -35,9 +42,9 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
it('Unable to submit proposal with public key', function () { it('Unable to submit proposal with public key', function () {
const expectedErrorTxt = `You are connected in a view only state for public key: ${vegaWalletPubKey}. In order to send transactions you must connect to a real wallet.`; const expectedErrorTxt = `You are connected in a view only state for public key: ${vegaWalletPubKey}. In order to send transactions you must connect to a real wallet.`;
cy.navigate_to('proposals'); navigateTo(navigation.proposals);
cy.go_to_make_new_proposal('Freeform'); goToMakeNewProposal('Freeform');
cy.enter_unique_freeform_proposal_body('50', 'pub key proposal test'); enterUniqueFreeFormProposalBody('50', 'pub key proposal test');
cy.getByTestId('dialog-content').within(() => { cy.getByTestId('dialog-content').within(() => {
cy.get('h1').should('have.text', 'Transaction failed'); cy.get('h1').should('have.text', 'Transaction failed');
cy.getByTestId('Error').should('have.text', expectedErrorTxt); cy.getByTestId('Error').should('have.text', expectedErrorTxt);

View File

@ -0,0 +1,42 @@
import {
navigateTo,
navigation,
verifyPageHeader,
} from '../../support/common.functions';
const viewToggle = '[data-testid="epoch-reward-view-toggle-total"]';
const warning = '[data-testid="callout"]';
context(
'Rewards Page - verify elements on page',
{ tags: '@regression' },
function () {
before('navigate to rewards page', function () {
cy.visit('/');
navigateTo(navigation.rewards);
});
describe('with wallets disconnected', function () {
it('should have REWARDS tab highlighted', function () {
verifyPageHeader('Rewards and fees');
});
it('should have rewards header visible', function () {
verifyPageHeader('Rewards and fees');
});
it('should have epoch warning', function () {
cy.get(warning)
.should('be.visible')
.and(
'have.text',
'Rewards are credited less than a minute after the epoch ends.This delay is set by a network parameter'
);
});
it('should have toggle for seeing total vs individual rewards', function () {
cy.get(viewToggle).should('be.visible');
});
});
}
);

View File

@ -1,3 +1,5 @@
import { navigateTo, navigation } from '../../support/common.functions';
const tokenDetailsTable = '.token-details'; const tokenDetailsTable = '.token-details';
const address = '[data-testid="token-address"]'; const address = '[data-testid="token-address"]';
const contract = '[data-testid="token-contract"]'; const contract = '[data-testid="token-contract"]';
@ -17,7 +19,8 @@ const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
context('Verify elements on Token page', { tags: '@smoke' }, function () { context('Verify elements on Token page', { tags: '@smoke' }, function () {
before('Visit token page', function () { before('Visit token page', function () {
cy.visit('/token'); cy.visit('/');
navigateTo(navigation.token);
}); });
describe('THE $VEGA TOKEN table', function () { describe('THE $VEGA TOKEN table', function () {
it('should have TOKEN ADDRESS', function () { it('should have TOKEN ADDRESS', function () {

View File

@ -1,4 +1,5 @@
import { trancheData } from '../../fixtures/mocks/tranches'; import { trancheData } from '../../fixtures/mocks/tranches';
import { navigateTo, navigation } from '../../support/common.functions';
const tranches = trancheData; const tranches = trancheData;
@ -8,7 +9,13 @@ context(
function () { function () {
before('visit homepage', function () { before('visit homepage', function () {
cy.intercept('GET', '**/tranches/stats', { tranches }); cy.intercept('GET', '**/tranches/stats', { tranches });
cy.visit('/token/tranches'); cy.visit('/');
});
it('Able to navigate to tranches page', function () {
navigateTo(navigation.supply);
cy.url().should('include', '/token/tranches');
cy.get('h1').should('contain.text', 'Vesting tranches');
}); });
// 1005-VEST-001 // 1005-VEST-001
@ -62,7 +69,7 @@ context(
}); });
it('Able to view tranches with less than 10 vega', function () { it('Able to view tranches with less than 10 vega', function () {
cy.navigate_to('supply'); navigateTo(navigation.supply);
cy.getByTestId('show-all-tranches').click(); cy.getByTestId('show-all-tranches').click();
cy.getByTestId('tranche-item') cy.getByTestId('tranche-item')
.should('have.length', 8) .should('have.length', 8)

View File

@ -1,210 +0,0 @@
/// <reference types="cypress" />
const validatorTitle = '[data-testid="validator-node-title"]';
const validatorId = '[data-testid="validator-id"]';
const validatorPubKey = '[data-testid="validator-public-key"]';
const ethAddressLink = '[data-testid="link"]';
const validatorStatus = '[data-testid="validator-status"]';
const totalStake = '[data-testid="total-stake"]';
const pendingStake = '[data-testid="pending-stake"]';
const stakedByOperator = '[data-testid="staked-by-operator"]';
const stakedByDelegates = '[data-testid="staked-by-delegates"]';
const stakeShare = '[data-testid="stake-percentage"]';
const stakedByOperatorToolTip = "[data-testid='staked-operator-tooltip']";
const stakedByDelegatesToolTip = "[data-testid='staked-delegates-tooltip']";
const totalStakedToolTip = "[data-testid='total-staked-tooltip']";
const unnormalisedVotingPowerToolTip =
"[data-testid='unnormalised-voting-power-tooltip']";
const normalisedVotingPowerToolTip =
"[data-testid='normalised-voting-power-tooltip']";
const performancePenaltyToolTip = "[data-testid='performance-penalty-tooltip']";
const overstakedPenaltyToolTip = "[data-testid='overstaked-penalty-tooltip']";
const totalPenaltyToolTip = "[data-testid='total-penalty-tooltip']";
const epochCountDown = '[data-testid="epoch-countdown"]';
const stakeNumberRegex = /^\d*\.?\d*$/;
context('Staking Page - verify elements on page', function () {
before('navigate to staking page', function () {
cy.visit('/validators');
});
describe(
'Should be able to see validator list from the staking page',
{ tags: '@regression' },
function () {
// 2001-STKE-050
it('Should be able to see validator names', function () {
cy.get('[col-id="validator"] > div > span')
.should('have.length.at.least', 1)
.each(($name) => {
cy.wrap($name).should('not.be.empty');
});
});
it('Should be able to see validator stake', function () {
cy.get('[col-id="stake"] > div > span > span')
.should('have.length.at.least', 1)
.each(($stake) => {
cy.wrap($stake).should('not.be.empty');
});
});
it('Should be able to see validator stake tooltip', function () {
cy.get('[col-id="stake"] > div > span > span').first().realHover();
cy.get(stakedByOperatorToolTip)
.invoke('text')
.should('contain', 'Staked by operator: 0.00');
cy.get(stakedByDelegatesToolTip)
.invoke('text')
.should('contain', 'Staked by delegates: 0.00');
cy.get(totalStakedToolTip)
.invoke('text')
.should('contain', 'Total stake: 0.00');
});
it('Should be able to see validator normalised voting power', function () {
cy.get('[col-id="normalisedVotingPower"] > div > span > span')
.should('have.length.at.least', 1)
.each(($vPower) => {
cy.wrap($vPower).should('not.be.empty');
});
});
it('Should be able to see validator voting power tooltip', function () {
cy.get('[col-id="normalisedVotingPower"] > div > span > span')
.first()
.realHover();
cy.get(unnormalisedVotingPowerToolTip)
.invoke('text')
.should('contain', 'Unnormalised voting power: 0.00%');
cy.get(normalisedVotingPowerToolTip)
.invoke('text')
.should('contain', 'Normalised voting power: 0.10%');
});
// 2002-SINC-018
it('Should be able to see validator total penalties', function () {
cy.get('[col-id="totalPenalties"] > div > span > span')
.should('have.length.at.least', 1)
.each(($penalties) => {
cy.wrap($penalties).should('contain.text', '0%');
});
});
it('Should be able to see validator penalties tooltip', function () {
cy.get('[col-id="totalPenalties"] > div > span > span').realHover();
cy.get(performancePenaltyToolTip)
.invoke('text')
.should('contain', 'Performance penalty: 100.00%');
cy.get(overstakedPenaltyToolTip)
.invoke('text')
.should('contain', 'Overstaked penalty:'); // value not asserted due to #2886
cy.get(totalPenaltyToolTip)
.invoke('text')
.should('contain', 'Total penalties: 0.00%');
});
it('Should be able to see validator pending stake', function () {
cy.get('[col-id="pendingStake"] > div > span')
.should('have.length.at.least', 1)
.each(($pendingStake) => {
cy.wrap($pendingStake).should('contain.text', '0.00');
});
});
}
);
// 2001-STKE-050
describe(
'Should be able to see static information about a validator',
{ tags: '@smoke' },
function () {
before('connect wallets and click on validator', function () {
cy.connectVegaWallet();
cy.click_on_validator_from_list(0);
});
// 2001-STKE-006
it('Should be able to see validator name', function () {
cy.get(validatorTitle).should('not.be.empty');
});
// 2001-STKE-007
it('Should be able to see validator id', function () {
cy.get(validatorId).should('not.be.empty');
});
// 2001-STKE-008
it('Should be able to see validator public key', function () {
cy.get(validatorPubKey).should('not.be.empty');
});
// 2001-STKE-010
it('Should be able to see Ethereum address', function () {
cy.get(ethAddressLink).should('not.be.empty').and('have.attr', 'href');
});
// TODO validators missing url for more information about them 2001-STKE-09
it('Should be able to see validator status', function () {
cy.get(validatorStatus).should('have.text', 'Consensus');
});
// 2001-STKE-012
it('Should be able to see total stake', function () {
cy.get(totalStake).invoke('text').should('match', stakeNumberRegex);
});
it('Should be able to see pending stake', function () {
cy.get(pendingStake).invoke('text').should('match', stakeNumberRegex);
});
it('Should be able to see staked by operator', function () {
cy.get(stakedByOperator)
.invoke('text')
.should('match', stakeNumberRegex);
});
it('Should be able to see staked by delegates', function () {
cy.get(stakedByDelegates)
.invoke('text')
.should('match', stakeNumberRegex);
});
// 2001-STKE-051
it('Should be able to see stake share in percentage', function () {
cy.get(stakeShare)
.invoke('text')
.then(($stakePercentage) => {
// The pattern must start at a word boundary (\b).
// The pattern cannot be immediately preceded by a dot ((?<!\.)).
// The pattern can be one of the following:
// A percentage value of zero (0%), or
// A non-zero percentage value that can be:
// A single digit (\d) between 0 and 9, or
// A two-digit number between 0 and 99 (\d{1,2}), or
// The number 100.
// The pattern can optionally include a decimal point and one or more digits after the decimal point ((?:(?<!100)\.\d+)?). However, if the number is 100, it cannot have a decimal point.
// The pattern must end with a percentage sign (%).
cy.wrap($stakePercentage).should(
'match',
/\b(?<!\.)(?:0+(?:\.0+)?%|(?:\d|\d{1,2}|100)(?:(?<!100)\.\d+)?)%/
);
});
});
// 2001-STKE-011 2002-SINC-001 2002-SINC-002
it('Should be able to see epoch information', function () {
const epochTitle = 'h3';
const nextEpochInfo = 'p';
cy.get(epochCountDown).within(() => {
cy.get(epochTitle).should('not.be.empty');
cy.get(nextEpochInfo).should('contain.text', 'Next epoch');
});
});
}
);
});

View File

@ -0,0 +1,246 @@
/// <reference types="cypress" />
import {
navigateTo,
navigation,
verifyPageHeader,
verifyTabHighlighted,
} from '../../support/common.functions';
import { clickOnValidatorFromList } from '../../support/staking.functions';
const guideLink = '[data-testid="staking-guide-link"]';
const validatorTitle = '[data-testid="validator-node-title"]';
const validatorId = '[data-testid="validator-id"]';
const validatorPubKey = '[data-testid="validator-public-key"]';
const ethAddressLink = '[data-testid="link"]';
const validatorStatus = '[data-testid="validator-status"]';
const totalStake = '[data-testid="total-stake"]';
const pendingStake = '[data-testid="pending-stake"]';
const stakedByOperator = '[data-testid="staked-by-operator"]';
const stakedByDelegates = '[data-testid="staked-by-delegates"]';
const stakeShare = '[data-testid="stake-percentage"]';
const stakedByOperatorToolTip = '[data-testid="staked-operator-tooltip"]';
const stakedByDelegatesToolTip = '[data-testid="staked-delegates-tooltip"]';
const totalStakedToolTip = '[data-testid="total-staked-tooltip"]';
const unnormalisedVotingPowerToolTip =
'[data-testid="unnormalised-voting-power-tooltip"]';
const normalisedVotingPowerToolTip =
'[data-testid="normalised-voting-power-tooltip"]';
const performancePenaltyToolTip = '[data-testid="performance-penalty-tooltip"]';
const overstakedPenaltyToolTip = '[data-testid="overstaked-penalty-tooltip"]';
const totalPenaltyToolTip = '[data-testid="total-penalty-tooltip"]';
const epochCountDown = '[data-testid="epoch-countdown"]';
const stakeNumberRegex = /^\d*\.?\d*$/;
context('Validators Page - verify elements on page', function () {
before('navigate to validators page', function () {
cy.visit('/');
navigateTo(navigation.validators);
});
describe('with wallets disconnected', { tags: '@smoke' }, function () {
describe('description section', function () {
it('Should have validators tab highlighted', function () {
verifyTabHighlighted(navigation.validators);
});
it('Should have validators ON VEGA header visible', function () {
verifyPageHeader('Validators');
});
it('Should have Staking Guide link visible', function () {
// 2001-STKE-003
cy.get(guideLink)
.should('be.visible')
.and('have.text', 'Read more about staking on Vega')
.and(
'have.attr',
'href',
'https://docs.vega.xyz/mainnet/concepts/vega-chain/#staking-on-vega'
);
});
});
describe(
'Should be able to see validator list from the staking page',
{ tags: '@regression' },
function () {
// 2001-STKE-050
it('Should be able to see validator names', function () {
cy.get('[col-id="validator"] > div > span')
.should('have.length.at.least', 1)
.each(($name) => {
cy.wrap($name).should('not.be.empty');
});
});
it('Should be able to see validator stake', function () {
cy.get('[col-id="stake"] > div > span > span')
.should('have.length.at.least', 1)
.each(($stake) => {
cy.wrap($stake).should('not.be.empty');
});
});
it('Should be able to see validator stake tooltip', function () {
cy.get('[col-id="stake"] > div > span > span').first().realHover();
cy.get(stakedByOperatorToolTip)
.invoke('text')
.should('contain', 'Staked by operator: 0.00');
cy.get(stakedByDelegatesToolTip)
.invoke('text')
.should('contain', 'Staked by delegates: 0.00');
cy.get(totalStakedToolTip)
.invoke('text')
.should('contain', 'Total stake: 0.00');
});
it('Should be able to see validator normalised voting power', function () {
cy.get('[col-id="normalisedVotingPower"] > div > span > span')
.should('have.length.at.least', 1)
.each(($vPower) => {
cy.wrap($vPower).should('not.be.empty');
});
});
it('Should be able to see validator voting power tooltip', function () {
cy.get('[col-id="normalisedVotingPower"] > div > span > span')
.first()
.realHover();
cy.get(unnormalisedVotingPowerToolTip)
.invoke('text')
.should('contain', 'Unnormalised voting power: 0.00%');
cy.get(normalisedVotingPowerToolTip)
.invoke('text')
.should('contain', 'Normalised voting power: 0.10%');
});
// 2002-SINC-018
it('Should be able to see validator total penalties', function () {
cy.get('[col-id="totalPenalties"] > div > span > span')
.should('have.length.at.least', 1)
.each(($penalties) => {
cy.wrap($penalties).should('contain.text', '0%');
});
});
it('Should be able to see validator penalties tooltip', function () {
cy.get('[col-id="totalPenalties"] > div > span > span').realHover();
cy.get(performancePenaltyToolTip)
.invoke('text')
.should('contain', 'Performance penalty: 100.00%');
cy.get(overstakedPenaltyToolTip)
.invoke('text')
.should('contain', 'Overstaked penalty:'); // value not asserted due to #2886
cy.get(totalPenaltyToolTip)
.invoke('text')
.should('contain', 'Total penalties: 0.00%');
});
it('Should be able to see validator pending stake', function () {
cy.get('[col-id="pendingStake"] > div > span')
.should('have.length.at.least', 1)
.each(($pendingStake) => {
cy.wrap($pendingStake).should('contain.text', '0.00');
});
});
}
);
// 2001-STKE-050
describe(
'Should be able to see static information about a validator',
{ tags: '@smoke' },
function () {
before('connect wallets and click on validator', function () {
cy.connectVegaWallet();
clickOnValidatorFromList(0);
});
// 2001-STKE-006
it('Should be able to see validator name', function () {
cy.get(validatorTitle).should('not.be.empty');
});
// 2001-STKE-007
it('Should be able to see validator id', function () {
cy.get(validatorId).should('not.be.empty');
});
// 2001-STKE-008
it('Should be able to see validator public key', function () {
cy.get(validatorPubKey).should('not.be.empty');
});
// 2001-STKE-010
it('Should be able to see Ethereum address', function () {
cy.get(ethAddressLink)
.should('not.be.empty')
.and('have.attr', 'href');
});
// TODO validators missing url for more information about them 2001-STKE-09
it('Should be able to see validator status', function () {
cy.get(validatorStatus).should('have.text', 'Consensus');
});
// 2001-STKE-012
it('Should be able to see total stake', function () {
cy.get(totalStake).invoke('text').should('match', stakeNumberRegex);
});
it('Should be able to see pending stake', function () {
cy.get(pendingStake).invoke('text').should('match', stakeNumberRegex);
});
it('Should be able to see staked by operator', function () {
cy.get(stakedByOperator)
.invoke('text')
.should('match', stakeNumberRegex);
});
it('Should be able to see staked by delegates', function () {
cy.get(stakedByDelegates)
.invoke('text')
.should('match', stakeNumberRegex);
});
// 2001-STKE-051
it('Should be able to see stake share in percentage', function () {
cy.get(stakeShare)
.invoke('text')
.then(($stakePercentage) => {
// The pattern must start at a word boundary (\b).
// The pattern cannot be immediately preceded by a dot ((?<!\.)).
// The pattern can be one of the following:
// A percentage value of zero (0%), or
// A non-zero percentage value that can be:
// A single digit (\d) between 0 and 9, or
// A two-digit number between 0 and 99 (\d{1,2}), or
// The number 100.
// The pattern can optionally include a decimal point and one or more digits after the decimal point ((?:(?<!100)\.\d+)?). However, if the number is 100, it cannot have a decimal point.
// The pattern must end with a percentage sign (%).
cy.wrap($stakePercentage).should(
'match',
/\b(?<!\.)(?:0+(?:\.0+)?%|(?:\d|\d{1,2}|100)(?:(?<!100)\.\d+)?)%/
);
});
});
// 2001-STKE-011 2002-SINC-001 2002-SINC-002
it('Should be able to see epoch information', function () {
const epochTitle = 'h3';
const nextEpochInfo = 'p';
cy.get(epochCountDown).within(() => {
cy.get(epochTitle).should('not.be.empty');
cy.get(nextEpochInfo).should('contain.text', 'Next epoch');
});
});
}
);
});
});

View File

@ -1,3 +1,12 @@
import {
navigateTo,
navigation,
verifyPageHeader,
verifyTabHighlighted,
} from '../../support/common.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
const connectButton = '[data-testid="connect-to-eth-btn"]';
const lockedTokensInVestingContract = '6,499,972.30'; const lockedTokensInVestingContract = '6,499,972.30';
context( context(
@ -5,12 +14,30 @@ context(
{ tags: '@smoke' }, { tags: '@smoke' },
function () { function () {
before('navigate to vesting page', function () { before('navigate to vesting page', function () {
cy.visit('/token/redeem'); cy.visit('/');
navigateTo(navigation.vesting);
});
describe('with wallets disconnected', function () {
it('should have vesting tab highlighted', function () {
verifyTabHighlighted(navigation.vesting);
});
it('should have VESTING header visible', function () {
verifyPageHeader('Vesting');
});
// 1005-VEST-018
it('should have connect Eth wallet button', function () {
cy.get(connectButton)
.should('be.visible')
.and('have.text', 'Connect Ethereum wallet');
});
}); });
describe('With Eth wallet connected', function () { describe('With Eth wallet connected', function () {
before('connect eth wallet', function () { before('connect eth wallet', function () {
cy.ethereum_wallet_connect(); ethereumWalletConnect();
cy.getByTestId('view-connected-eth-btn').click(); cy.getByTestId('view-connected-eth-btn').click();
}); });
@ -105,7 +132,6 @@ context(
'All the tokens in this tranche are locked and can not be redeemed yet.' 'All the tokens in this tranche are locked and can not be redeemed yet.'
); );
}); });
cy.connectVegaWallet();
}); });
}); });
} }

View File

@ -1,3 +1,6 @@
import { convertTokenValueToNumber } from '../../support/common.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
const walletContainer = 'aside [data-testid="ethereum-wallet"]'; const walletContainer = 'aside [data-testid="ethereum-wallet"]';
const walletHeader = '[data-testid="wallet-header"] h1'; const walletHeader = '[data-testid="wallet-header"] h1';
const connectToEthButton = const connectToEthButton =
@ -87,7 +90,7 @@ context(
// 0004-EWAL-001 0004-EWAL-002 // 0004-EWAL-001 0004-EWAL-002
describe('when Ethereum wallet connected', function () { describe('when Ethereum wallet connected', function () {
before('connect to Ethereum wallet', function () { before('connect to Ethereum wallet', function () {
cy.ethereum_wallet_connect(); ethereumWalletConnect();
}); });
it('should have ETHEREUM KEY header visible', function () { it('should have ETHEREUM KEY header visible', function () {
@ -178,22 +181,25 @@ context(
.within(() => { .within(() => {
cy.get(currencyValue) cy.get(currencyValue)
.invoke('text') .invoke('text')
.convert_token_value_to_number() .then((currencyValueTxt) => {
.as('value'); convertTokenValueToNumber(currencyValueTxt).as('value');
});
cy.get(currencyLocked) cy.get(currencyLocked)
.invoke('text') .invoke('text')
.convert_token_value_to_number() .then((currencyLockedTxt) => {
.as('locked'); convertTokenValueToNumber(currencyLockedTxt).as('locked');
});
cy.get(currencyUnlocked) cy.get(currencyUnlocked)
.invoke('text') .invoke('text')
.convert_token_value_to_number() .then((currencyUnlockedTxt) => {
.as('unlocked'); convertTokenValueToNumber(currencyUnlockedTxt).as('unlocked');
});
}) })
.then(function () { .then(function () {
expect(parseFloat(this.value).toFixed(1)).to.equal( expect(parseFloat(this.value).toFixed(1)).to.equal(
parseFloat( (Math.round((this.locked + this.unlocked) * 100) / 100).toFixed(
Math.round((this.locked + this.unlocked) * 100) / 100 1
).toFixed(1) )
); );
}); });
}); });
@ -247,16 +253,19 @@ context(
.within(() => { .within(() => {
cy.get(currencyValue) cy.get(currencyValue)
.invoke('text') .invoke('text')
.convert_token_value_to_number() .then((currencyValueTxt) => {
.as('value'); convertTokenValueToNumber(currencyValueTxt).as('value');
});
cy.get(currencyLocked) cy.get(currencyLocked)
.invoke('text') .invoke('text')
.convert_token_value_to_number() .then((currencyLockedTxt) => {
.as('locked'); convertTokenValueToNumber(currencyLockedTxt).as('locked');
});
cy.get(currencyUnlocked) cy.get(currencyUnlocked)
.invoke('text') .invoke('text')
.convert_token_value_to_number() .then((currencyUnlockedTxt) => {
.as('unlocked'); convertTokenValueToNumber(currencyUnlockedTxt).as('unlocked');
});
}) })
.then(function () { .then(function () {
expect(this.value).to.equal(this.locked + this.unlocked); expect(this.value).to.equal(this.locked + this.unlocked);

View File

@ -1,4 +1,7 @@
import { truncateByChars } from '@vegaprotocol/utils'; import { truncateByChars } from '@vegaprotocol/utils';
import { waitForSpinner } from '../../support/common.functions';
import { vegaWalletTeardown } from '../../support/wallet-teardown.functions';
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
const walletContainer = 'aside [data-testid="vega-wallet"]'; const walletContainer = 'aside [data-testid="vega-wallet"]';
const walletHeader = '[data-testid="wallet-header"] h1'; const walletHeader = '[data-testid="wallet-header"] h1';
@ -129,7 +132,7 @@ context(
before('connect vega wallet', function () { before('connect vega wallet', function () {
cy.visit('/'); cy.visit('/');
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.vega_wallet_teardown(); vegaWalletTeardown();
}); });
// 0002-WCON-007 // 0002-WCON-007
@ -158,7 +161,7 @@ context(
cy.get(walletContainer).within(() => { cy.get(walletContainer).within(() => {
cy.get(currencyTitle) cy.get(currencyTitle)
.should('be.visible') .should('be.visible')
.and('have.text', `VEGAAssociated`); .and('contain.text', `VEGAAssociated`);
}); });
}); });
@ -167,14 +170,19 @@ context(
{ tags: '@smoke' }, { tags: '@smoke' },
function () { function () {
cy.get(walletContainer).within(() => { cy.get(walletContainer).within(() => {
cy.get(currencyValue).should('be.visible').and('have.text', `0.00`); cy.get(currencyValue)
.should('be.visible')
.and('contain.text', `0.00`);
}); });
} }
); );
it('should have Unstaked value visible', { tags: '@smoke' }, function () { it('should have Unstaked value visible', { tags: '@smoke' }, function () {
cy.get(walletContainer).within(() => { cy.get(walletContainer).within(() => {
cy.get(vegaUnstaked).should('be.visible').and('have.text', `0.00`); cy.get(vegaUnstaked)
.should('be.visible')
.invoke('text')
.and('not.be.empty');
}); });
}); });
@ -300,16 +308,17 @@ context(
before('faucet assets to connected vega wallet', function () { before('faucet assets to connected vega wallet', function () {
for (const { id, amount } of assets) { for (const { id, amount } of assets) {
cy.vega_wallet_faucet_assets_without_check( vegaWalletFaucetAssetsWithoutCheck(id, amount, vegaWalletPublicKey);
id,
amount,
vegaWalletPublicKey
);
} }
cy.reload(); cy.reload();
cy.wait_for_spinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
cy.ethereum_wallet_connect(); cy.get(walletContainer).within(() => {
cy.getByTestId('currency-title', txTimeout).should(
'have.length.at.least',
5
);
});
}); });
for (const { id, name, expectedAmount } of assets) { for (const { id, name, expectedAmount } of assets) {
@ -323,8 +332,9 @@ context(
.contains(id) .contains(id)
.parent() .parent()
.siblings() .siblings()
.within((el) => { .invoke('text')
const value = parseFloat(el.text()); .then((el) => {
const value = parseFloat(el);
cy.wrap(value).should('be.gte', parseFloat(expectedAmount)); cy.wrap(value).should('be.gte', parseFloat(expectedAmount));
}); });

View File

@ -0,0 +1,35 @@
import {
navigateTo,
navigation,
verifyPageHeader,
verifyTabHighlighted,
} from '../../support/common.functions';
const connectToVegaBtn = '[data-testid="connect-to-vega-wallet-btn"]';
context(
'Withdraw Page - verify elements on page',
{ tags: '@smoke' },
function () {
before('navigate to withdrawals page', function () {
cy.visit('/');
navigateTo(navigation.withdraw);
});
describe('with wallets disconnected', function () {
it('should have withdraw tab highlighted', function () {
verifyTabHighlighted(navigation.withdraw);
});
it('should have WITHDRAW header visible', function () {
verifyPageHeader('Withdrawals');
});
it('should have connect Vega wallet button', function () {
cy.get(connectToVegaBtn)
.should('be.visible')
.and('have.text', 'Connect Vega wallet');
});
});
}
);

View File

@ -0,0 +1,128 @@
export interface testFreeformProposal {
rationale: {
title: string;
description: string;
};
terms: {
closingTimestamp: number;
};
}
export interface networkParameters {
'blockchains.ethereumConfig': string;
'governance.proposal.asset.maxClose': string;
'governance.proposal.asset.maxEnact': string;
'governance.proposal.asset.minClose': string;
'governance.proposal.asset.minEnact': string;
'governance.proposal.asset.minProposerBalance': string;
'governance.proposal.asset.minVoterBalance': string;
'governance.proposal.asset.requiredMajority': string;
'governance.proposal.asset.requiredParticipation': string;
'governance.proposal.freeform.maxClose': string;
'governance.proposal.freeform.minClose': string;
'governance.proposal.freeform.minProposerBalance': string;
'governance.proposal.freeform.minVoterBalance': string;
'governance.proposal.freeform.requiredMajority': string;
'governance.proposal.freeform.requiredParticipation': string;
'governance.proposal.market.maxClose': string;
'governance.proposal.market.maxEnact': string;
'governance.proposal.market.minClose': string;
'governance.proposal.market.minEnact': string;
'governance.proposal.market.minProposerBalance': string;
'governance.proposal.market.minVoterBalance': string;
'governance.proposal.market.requiredMajority': string;
'governance.proposal.market.requiredParticipation': string;
'governance.proposal.updateAsset.maxClose': string;
'governance.proposal.updateAsset.maxEnact': string;
'governance.proposal.updateAsset.minClose': string;
'governance.proposal.updateAsset.minEnact': string;
'governance.proposal.updateAsset.minProposerBalance': string;
'governance.proposal.updateAsset.minVoterBalance': string;
'governance.proposal.updateAsset.requiredMajority': string;
'governance.proposal.updateAsset.requiredParticipation': string;
'governance.proposal.updateMarket.maxClose': string;
'governance.proposal.updateMarket.maxEnact': string;
'governance.proposal.updateMarket.minClose': string;
'governance.proposal.updateMarket.minEnact': string;
'governance.proposal.updateMarket.minProposerBalance': string;
'governance.proposal.updateMarket.minProposerEquityLikeShare': string;
'governance.proposal.updateMarket.minVoterBalance': string;
'governance.proposal.updateMarket.requiredMajority': string;
'governance.proposal.updateMarket.requiredMajorityLP': string;
'governance.proposal.updateMarket.requiredParticipation': string;
'governance.proposal.updateMarket.requiredParticipationLP': string;
'governance.proposal.updateNetParam.maxClose': string;
'governance.proposal.updateNetParam.maxEnact': string;
'governance.proposal.updateNetParam.minClose': string;
'governance.proposal.updateNetParam.minEnact': string;
'governance.proposal.updateNetParam.minProposerBalance': string;
'governance.proposal.updateNetParam.minVoterBalance': string;
'governance.proposal.updateNetParam.requiredMajority': string;
'governance.proposal.updateNetParam.requiredParticipation': string;
'limits.assets.proposeEnabledFrom': string;
'limits.markets.maxPeggedOrders': string;
'limits.markets.proposeEnabledFrom': string;
'market.auction.maximumDuration': string;
'market.auction.minimumDuration': string;
'market.fee.factors.infrastructureFee': string;
'market.fee.factors.makerFee': string;
'market.liquidity.bondPenaltyParameter': string;
'market.liquidity.maximumLiquidityFeeFactorLevel': string;
'market.liquidity.minimum.probabilityOfTrading.lpOrders': string;
'market.liquidity.probabilityOfTrading.tau.scaling': string;
'market.liquidity.providers.fee.distributionTimeStep': string;
'market.liquidity.stakeToCcyVolume': string;
'market.liquidity.targetstake.triggering.ratio': string;
'market.liquidityProvision.minLpStakeQuantumMultiple': string;
'market.liquidityProvision.shapes.maxSize': string;
'market.margin.scalingFactors': string;
'market.monitor.price.defaultParameters': string;
'market.stake.target.scalingFactor': string;
'market.stake.target.timeWindow': string;
'market.value.windowLength': string;
'network.checkpoint.timeElapsedBetweenCheckpoints': string;
'network.floatingPointUpdates.delay': string;
'network.markPriceUpdateMaximumFrequency': string;
'network.transaction.defaultgas': string;
'network.transactions.maxgasperblock': string;
'network.transactions.minBlockCapacity': string;
'network.validators.ersatz.multipleOfTendermintValidators': string;
'network.validators.ersatz.rewardFactor': string;
'network.validators.incumbentBonus': string;
'network.validators.minimumEthereumEventsForNewValidator': string;
'network.validators.multisig.numberOfSigners': string;
'network.validators.tendermint.number': string;
'reward.asset': string;
'reward.staking.delegation.competitionLevel': string;
'reward.staking.delegation.delegatorShare': string;
'reward.staking.delegation.maxPayoutPerEpoch': string;
'reward.staking.delegation.maxPayoutPerParticipant': string;
'reward.staking.delegation.minValidators': string;
'reward.staking.delegation.minimumValidatorStake': string;
'reward.staking.delegation.optimalStakeMultiplier': string;
'reward.staking.delegation.payoutDelay': string;
'reward.staking.delegation.payoutFraction': string;
'rewards.marketCreationQuantumMultiple': string;
'snapshot.interval.length': string;
'spam.pow.difficulty': string;
'spam.pow.hashFunction': string;
'spam.pow.increaseDifficulty': string;
'spam.pow.numberOfPastBlocks': string;
'spam.pow.numberOfTxPerBlock': string;
'spam.protection.delegation.min.tokens': string;
'spam.protection.max.batchSize': string;
'spam.protection.max.delegations': string;
'spam.protection.max.proposals': string;
'spam.protection.max.votes': string;
'spam.protection.maxUserTransfersPerEpoch': string;
'spam.protection.minMultisigUpdates': string;
'spam.protection.minimumWithdrawalQuantumMultiple': string;
'spam.protection.proposal.min.tokens': string;
'spam.protection.voting.min.tokens': string;
'transfer.fee.factor': string;
'transfer.minTransferQuantumMultiple': string;
'validator.performance.scaling.factor': string;
'validators.delegation.minAmount': string;
'validators.epoch.length': string;
'validators.vote.required': string;
}

View File

@ -1,87 +0,0 @@
const epochTimeout = Cypress.env('epochTimeout');
const txTimeout = Cypress.env('txTimeout');
Cypress.Commands.add(
'convert_token_value_to_number',
{ prevSubject: true },
(subject) => {
return parseFloat(subject.replace(/,/g, ''));
}
);
const navigation = {
section: '[data-testid="navigation"]',
vesting: '[href="/token/redeem"]',
validators: '[href="/validators"]',
rewards: '[href="/rewards"]',
withdraw: '[href="/token/withdraw"]',
proposals: '[href="/proposals"]',
pageSpinner: '[data-testid="splash-loader"]',
supply: '[href="/token/tranches"]',
token: '[href="/token"]',
};
const topLevelRoutes = ['proposals', 'validators', 'rewards'];
const tokenDropDown = 'state-trigger';
Cypress.Commands.add('navigate_to', (page) => {
if (!topLevelRoutes.includes(page)) {
// FIXME: Timeout madness
cy.getByTestId(tokenDropDown, { timeout: 60000 }).eq(0).click();
cy.get('[data-testid="token-dropdown"]:visible').within(() => {
cy.get(navigation[page]).eq(0).click();
});
} else {
return cy.get(navigation.section, { timeout: 10000 }).within(() => {
cy.get(navigation[page]).eq(0).click();
});
}
});
Cypress.Commands.add('verify_tab_highlighted', (page) => {
return cy.get(navigation.section).within(() => {
if (!topLevelRoutes.includes(page)) {
cy.getByTestId(tokenDropDown, { timeout: 10000 }).eq(0).click();
cy.get('[data-testid="token-dropdown"]:visible').within(() => {
cy.get(navigation[page]).should('have.attr', 'aria-current');
});
} else {
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);
});
Cypress.Commands.add('wait_for_spinner', () => {
cy.get(navigation.pageSpinner, Cypress.env('epochTimeout')).should('exist');
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
});
// This is a workaround function to begin tests with associating tokens without failing
// Should be removed when eth transaction bug is fixed
export function associateTokenStartOfTests() {
cy.highlight(`Associating tokens for first time`);
cy.ethereum_wallet_connect();
cy.connectVegaWallet();
cy.get('[href="/token/associate"]:visible').first().click();
cy.getByTestId('associate-radio-wallet', { timeout: 30000 }).click();
cy.getByTestId('token-amount-input', epochTimeout).type('1');
cy.getByTestId('token-input-submit-button', txTimeout)
.should('be.enabled')
.click();
cy.contains(
`Associating with Vega key. Waiting for ${Cypress.env(
'blockConfirmations'
)} more confirmations..`,
txTimeout
).should('be.visible');
cy.getByTestId('associated-amount', txTimeout).should('contain.text', '1');
// Wait is needed to allow time for transaction to complete
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(10000);
cy.vega_wallet_teardown();
cy.clearLocalStorage();
}

View File

@ -0,0 +1,86 @@
const tokenDropDown = 'state-trigger';
const txTimeout = Cypress.env('txTimeout');
export enum navigation {
section = 'nav',
vesting = '[href="/token/redeem"]',
validators = '[href="/validators"]',
rewards = '[href="/rewards"]',
withdraw = '[href="/token/withdraw"]',
proposals = '[href="/proposals"]',
pageSpinner = '[data-testid="splash-loader"]',
supply = '[href="/token/tranches"]',
token = '[href="/token"]',
}
export function convertTokenValueToNumber(subject: string) {
return cy.wrap(parseFloat(subject.replace(/,/g, '')));
}
const topLevelRoutes = [
navigation.proposals,
navigation.validators,
navigation.rewards,
];
export function navigateTo(page: navigation) {
if (!topLevelRoutes.includes(page)) {
cy.getByTestId(tokenDropDown, { timeout: 10000 }).eq(0).click();
cy.getByTestId('token-dropdown').within(() => {
cy.get(page).eq(0).click();
});
} else {
return cy.get(navigation.section, { timeout: 10000 }).within(() => {
cy.get(page).eq(0).click();
});
}
}
export function verifyTabHighlighted(page: navigation) {
return cy.get(navigation.section).within(() => {
if (!topLevelRoutes.includes(page)) {
cy.getByTestId(tokenDropDown, { timeout: 10000 }).eq(0).click();
cy.get('[data-testid="token-dropdown"]:visible').within(() => {
cy.get(page).should('have.attr', 'aria-current');
});
} else {
cy.get(page).should('have.attr', 'aria-current');
}
});
}
export function verifyPageHeader(text: string) {
return cy.get('header h1').should('be.visible').and('have.text', text);
}
export function waitForSpinner() {
cy.get(navigation.pageSpinner, Cypress.env('epochTimeout')).should('exist');
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
}
export function verifyUnstakedBalance(amount: number) {
cy.getByTestId('vega-wallet-balance-unstaked', txTimeout).should(
'contain',
amount,
txTimeout
);
}
export function verifyStakedBalance(amount: number) {
cy.getByTestId('vega-wallet-balance-staked-validators', txTimeout)
.should('contain', amount, txTimeout)
.and('contain', '…');
}
export function verifyEthWalletTotalAssociatedBalance(amount: string) {
cy.getByTestId('currency-locked', txTimeout)
.should('contain', amount)
.and('be.visible');
}
export function verifyEthWalletAssociatedBalance(amount: string) {
cy.getByTestId('eth-wallet-associated-balances', txTimeout)
.contains(Cypress.env('vegaWalletPublicKeyShort'), txTimeout)
.parent(txTimeout)
.should('contain', amount, txTimeout);
}

View File

@ -1,228 +0,0 @@
const newProposalButton = '[data-testid="new-proposal-link"]';
const proposalInformationTableRows = '[data-testid="key-value-table-row"]';
const proposalListItem = '[data-testid="proposals-list-item"]';
const newProposalTitle = '[data-testid="proposal-title"]';
const newProposalDescription = '[data-testid="proposal-description"]';
const proposalDetails = '[data-testid="proposal-details"]';
const rawProposalData = '[data-testid="proposal-data"]';
const voteButtons = '[data-testid="vote-buttons"]';
const dialogTitle = '[data-testid="dialog-title"]';
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const dialogCloseButton = '[data-testid="dialog-close"]';
const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 };
Cypress.Commands.add(
'convert_unix_timestamp_to_governance_data_table_date_format',
(unixTimestamp, monthTextLength = 'longMonth') => {
let dateSupplied = new Date(unixTimestamp * 1000),
year = dateSupplied.getFullYear(),
months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
],
month = months[dateSupplied.getMonth()],
shortMonth = months[dateSupplied.getMonth()].substring(0, 3),
date = dateSupplied.getDate();
if (monthTextLength === 'longMonth') return `${date} ${month} ${year}`;
else return `${date} ${shortMonth} ${year}`;
}
);
Cypress.Commands.add(
'create_ten_digit_unix_timestamp_for_specified_days',
(durationDays) => {
let today = new Date();
let timestamp = today.setDate(today.getDate() + parseInt(durationDays));
timestamp = Math.floor(timestamp / 1000);
return timestamp;
}
);
Cypress.Commands.add('enter_raw_proposal_body', (timestamp) => {
cy.fixture('/proposals/raw.json').then((rawProposal) => {
rawProposal.terms.closingTimestamp = timestamp;
rawProposal.rationale.title += timestamp;
let proposalPayload = JSON.stringify(rawProposal);
cy.get(rawProposalData).type(proposalPayload, {
parseSpecialCharSequences: false,
delay: 2,
});
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wrap(rawProposal);
});
});
Cypress.Commands.add(
'enter_unique_freeform_proposal_body',
(timestamp, proposalTitle) => {
cy.get(newProposalTitle).type(proposalTitle);
cy.get(newProposalDescription).type(
'this is a e2e freeform proposal description'
);
cy.get(proposalVoteDeadline).clear().click().type(timestamp);
cy.getByTestId('proposal-submit').should('be.visible').click();
}
);
Cypress.Commands.add(
'get_submitted_proposal_from_proposal_list',
(proposalTitle) => {
cy.get_proposal_id_from_list(proposalTitle).then(() => {
cy.get('@proposalIdText').then((proposalId) => {
return cy.get(`#${proposalId}`);
});
});
}
);
Cypress.Commands.add('get_proposal_id_from_list', (proposalTitle) => {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.within(() => {
cy.get(proposalDetails)
.invoke('text')
.then((proposalIdText) => {
let newProposalId;
if (proposalIdText.includes('Freeform proposal')) {
newProposalId = proposalIdText.replace('Freeform proposal: ', '');
}
cy.wrap(newProposalId).as('proposalIdText');
});
});
});
Cypress.Commands.add(
'get_governance_proposal_date_format_for_specified_days',
(days, shortOrLong) => {
cy.create_ten_digit_unix_timestamp_for_specified_days(days).then((date) => {
cy.convert_unix_timestamp_to_governance_data_table_date_format(
date,
shortOrLong
).then((convertedDate) => {
return convertedDate;
});
});
}
);
Cypress.Commands.add('get_proposal_information_from_table', (heading) => {
cy.get(proposalInformationTableRows).contains(heading).siblings();
});
Cypress.Commands.add('vote_for_proposal', (vote) => {
cy.contains('Vote breakdown').should('be.visible', { timeout: 10000 });
cy.get(voteButtons).contains(vote).click();
cy.get(dialogTitle).should('have.text', 'Transaction complete');
cy.get(dialogCloseButton).click();
});
Cypress.Commands.add('wait_for_proposal_sync', () => {
// This is a workaround function required because after posting a proposal
// and waiting for the ProposalEvent network call to respond there can still be a few seconds
// before proposal appears in the list - so rather than hard coded wait - we just wait on the
// delegation checks that are performed on the governance page.
cy.intercept('POST', '/query', (req) => {
if (req.body.operationName === 'Delegations') {
req.alias = 'proposalDelegationsCompletion';
}
});
// waiting for two network calls
cy.wait(['@proposalDelegationsCompletion', '@proposalDelegationsCompletion']);
// Turn off this intercept from here on in
cy.intercept('POST', '/query', (req) => {
if (req.body.operationName === 'Delegations') {
req.continue();
}
});
});
Cypress.Commands.add('navigate_to_page_if_not_already_loaded', (section) => {
cy.url().then((url) => {
if (url != `http://localhost:4210/${section}`) {
cy.navigate_to(section);
}
});
});
Cypress.Commands.add('get_sort_order_of_supplied_array', (suppliedArray) => {
const tempArray = [];
for (let index = 1; index < suppliedArray.length; index++) {
tempArray.push(
suppliedArray[index - 1].localeCompare(suppliedArray[index])
);
}
if (tempArray.every((n) => n <= 0)) return 'ascending';
else if (tempArray.every((n) => n >= 0)) return 'descending';
else return 'unsorted';
});
Cypress.Commands.add('go_to_make_new_proposal', (proposalType) => {
cy.navigate_to_page_if_not_already_loaded('proposals');
cy.get(newProposalButton).should('be.visible').click();
cy.url().should('include', '/proposals/propose');
cy.get('li').should('contain.text', proposalType).and('be.visible');
cy.get('li').contains(proposalType).click();
});
Cypress.Commands.add('wait_for_proposal_submitted', () => {
cy.contains('Awaiting network confirmation', epochTimeout).should(
'be.visible'
);
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
cy.get(dialogCloseButton).click();
});
export function createRawProposal(proposerBalance) {
if (proposerBalance)
cy.ensure_specified_unstaked_tokens_are_associated(proposerBalance);
cy.go_to_make_new_proposal('raw proposal');
cy.create_ten_digit_unix_timestamp_for_specified_days('8').then(
(closingDateTimestamp) => {
cy.enter_raw_proposal_body(closingDateTimestamp).as('rawProposal');
}
);
cy.wait_for_proposal_submitted();
cy.wait_for_proposal_sync();
cy.navigate_to('proposals');
}
export function generateFreeFormProposalTitle() {
const randomNum = Math.floor(Math.random() * 1000) + 1;
return randomNum + ': Freeform e2e proposal';
}
export function createFreeformProposal(proposalTitle) {
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
cy.enter_unique_freeform_proposal_body('50', proposalTitle);
cy.wait_for_proposal_submitted();
cy.wait_for_proposal_sync();
cy.getByTestId('proposal-title').invoke('text').as('proposalTitle');
cy.navigate_to('proposals');
}
export const governanceProposalType = {
NETWORK_PARAMETER: 'Network parameter',
NEW_MARKET: 'New market',
UPDATE_MARKET: 'Update market',
NEW_ASSET: 'New asset',
FREEFORM: 'Freeform',
RAW: 'raw proposal',
};

View File

@ -0,0 +1,215 @@
import { navigateTo, navigation } from './common.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from './staking.functions';
const newProposalButton = '[data-testid="new-proposal-link"]';
const proposalInformationTableRows = '[data-testid="key-value-table-row"]';
const proposalListItem = '[data-testid="proposals-list-item"]';
const newProposalTitle = '[data-testid="proposal-title"]';
const newProposalDescription = '[data-testid="proposal-description"]';
const proposalDetails = '[data-testid="proposal-details"]';
const rawProposalData = '[data-testid="proposal-data"]';
const voteButtons = '[data-testid="vote-buttons"]';
const dialogTitle = '[data-testid="dialog-title"]';
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const dialogCloseButton = '[data-testid="dialog-close"]';
const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 };
export function convertUnixTimestampToDateformat(
unixTimestamp: number,
monthTextLength = 'longMonth'
) {
const dateSupplied = new Date(unixTimestamp * 1000);
const year = dateSupplied.getFullYear();
const months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
const month = months[dateSupplied.getMonth()];
const shortMonth = months[dateSupplied.getMonth()].substring(0, 3),
date = dateSupplied.getDate();
if (monthTextLength === 'longMonth') {
return cy.wrap(`${date} ${month} ${year}`);
} else return cy.wrap(`${date} ${shortMonth} ${year}`);
}
export function createTenDigitUnixTimeStampForSpecifiedDays(
durationDays: number
) {
const today = new Date();
let timestamp = today.setDate(today.getDate() + durationDays);
return (timestamp = Math.floor(timestamp / 1000));
}
export function enterRawProposalBody(timestamp: number) {
cy.fixture('/proposals/raw.json').then((rawProposal) => {
rawProposal.terms.closingTimestamp = timestamp;
rawProposal.rationale.title += timestamp;
const proposalPayload = JSON.stringify(rawProposal);
cy.get(rawProposalData).type(proposalPayload, {
parseSpecialCharSequences: false,
delay: 2,
});
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wrap(rawProposal).as('rawProposal');
});
}
export function enterUniqueFreeFormProposalBody(
timestamp: string,
proposalTitle: string
) {
cy.get(newProposalTitle).type(proposalTitle);
cy.get(newProposalDescription).type(
'this is a e2e freeform proposal description'
);
cy.get(proposalVoteDeadline).clear().click().type(timestamp);
cy.getByTestId('proposal-submit').should('be.visible').click();
}
export function getSubmittedProposalFromProposalList(proposalTitle: string) {
getProposalIdFromList(proposalTitle);
cy.get('@proposalIdText').then((proposalId) => {
cy.get(`#${proposalId}`).as('submittedProposal');
});
return cy.get('@submittedProposal');
}
export function getProposalIdFromList(proposalTitle: string) {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.within(() => {
cy.get(proposalDetails)
.invoke('text')
.then((proposalIdText) => {
let newProposalId;
if (proposalIdText.includes('Freeform proposal')) {
newProposalId = proposalIdText.replace('Freeform proposal: ', '');
}
cy.wrap(newProposalId).as('proposalIdText');
});
});
}
export function getGovernanceProposalDateFormatForSpecifiedDays(
days: number,
shortOrLong?: string
) {
return convertUnixTimestampToDateformat(
createTenDigitUnixTimeStampForSpecifiedDays(days),
shortOrLong
);
}
export function getProposalInformationFromTable(heading: string) {
return cy.get(proposalInformationTableRows).contains(heading).siblings();
}
export function voteForProposal(vote: string) {
cy.contains('Vote breakdown').should('be.visible', { timeout: 10000 });
cy.get(voteButtons).contains(vote).click();
cy.get(dialogTitle, proposalTimeout).should(
'have.text',
'Transaction complete'
);
cy.get(dialogCloseButton).click();
}
export function waitForProposalSync() {
// This is a workaround function required because after posting a proposal
// and waiting for the ProposalEvent network call to respond there can still be a few seconds
// before proposal appears in the list - so rather than hard coded wait - we just wait on the
// delegation checks that are performed on the governance page.
cy.intercept('POST', '/query', (req) => {
if (req.body.operationName === 'Delegations') {
req.alias = 'proposalDelegationsCompletion';
}
});
// waiting for two network calls
cy.wait(['@proposalDelegationsCompletion', '@proposalDelegationsCompletion']);
// Turn off this intercept from here on in
cy.intercept('POST', '/query', (req) => {
if (req.body.operationName === 'Delegations') {
req.continue();
}
});
}
export function getSortOrderOfSuppliedArray(suppliedArray: string[]) {
const tempArray = [];
for (let index = 1; index < suppliedArray.length; index++) {
tempArray.push(
suppliedArray[index - 1].localeCompare(suppliedArray[index])
);
}
if (tempArray.every((n) => n <= 0)) return 'ascending';
else if (tempArray.every((n) => n >= 0)) return 'descending';
else return 'unsorted';
}
export function goToMakeNewProposal(proposalType: string) {
navigateTo(navigation.proposals);
cy.get(newProposalButton).should('be.visible').click();
cy.url().should('include', '/proposals/propose');
cy.get('li').should('contain.text', proposalType).and('be.visible');
cy.get('li').contains(proposalType).click();
}
export function waitForProposalSubmitted() {
cy.contains('Awaiting network confirmation', epochTimeout).should(
'be.visible'
);
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
cy.get(dialogCloseButton).click();
}
export function createRawProposal(proposerBalance?: string) {
if (proposerBalance) {
ensureSpecifiedUnstakedTokensAreAssociated(proposerBalance);
}
goToMakeNewProposal(governanceProposalType.RAW);
enterRawProposalBody(createTenDigitUnixTimeStampForSpecifiedDays(8));
waitForProposalSubmitted();
waitForProposalSync();
navigateTo(navigation.proposals);
}
export function generateFreeFormProposalTitle() {
const randomNum = Math.floor(Math.random() * 1000) + 1;
return randomNum + ': Freeform e2e proposal';
}
export function createFreeformProposal(proposalTitle: string) {
goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody('50', proposalTitle);
waitForProposalSubmitted();
waitForProposalSync();
cy.getByTestId('proposal-title').invoke('text').as('proposalTitle');
navigateTo(navigation.proposals);
}
export const governanceProposalType = {
NETWORK_PARAMETER: 'Network parameter',
NEW_MARKET: 'New market',
UPDATE_MARKET: 'Update market',
NEW_ASSET: 'New asset',
FREEFORM: 'Freeform',
RAW: 'raw proposal',
};

View File

@ -0,0 +1,20 @@
/// <reference types="cypress" />
declare namespace Cypress {
// specify additional properties in the TestConfig object
// in our case we will add "tags" property
interface SuiteConfigOverrides {
/**
* List of tags for this test
* @example a single tag
* it('logs in', { tags: '@smoke' }, () => { ... })
* @example multiple tags
* it('works', { tags: ['@smoke', '@slow'] }, () => { ... })
*/
tags?: string | string[];
}
interface Cypress {
grep?: (grep?: string, tags?: string, burn?: string) => void;
}
}

View File

@ -1,12 +1,12 @@
import '@vegaprotocol/cypress'; import '@vegaprotocol/cypress';
import 'cypress-real-events/support'; import 'cypress-real-events/support';
import './common.functions.js'; import './common.functions.ts';
import './staking.functions.js'; import './staking.functions.ts';
import './governance.functions.js'; import './governance.functions.ts';
import './wallet-eth.functions.js'; import './wallet-eth.functions.ts';
import './wallet-teardown.functions.js'; import './wallet-teardown.functions.ts';
import './wallet-vega.functions.js'; import './wallet-vega.functions.ts';
import './proposal.functions.ts'; import './proposal.functions.ts';
import registerCypressGrep from '@cypress/grep'; import registerCypressGrep from '@cypress/grep';
import { aliasGQLQuery } from '@vegaprotocol/cypress'; import { aliasGQLQuery } from '@vegaprotocol/cypress';

View File

@ -1,3 +1,5 @@
import { vegaWalletTeardown } from './wallet-teardown.functions';
const tokenAmountInputBox = '[data-testid="token-amount-input"]'; const tokenAmountInputBox = '[data-testid="token-amount-input"]';
const tokenSubmitButton = '[data-testid="token-input-submit-button"]'; const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
const tokenInputApprove = '[data-testid="token-input-approve-button"]'; const tokenInputApprove = '[data-testid="token-input-approve-button"]';
@ -21,44 +23,47 @@ const dialogCloseButton = '[data-testid="dialog-close"]';
const txTimeout = Cypress.env('txTimeout'); const txTimeout = Cypress.env('txTimeout');
const epochTimeout = Cypress.env('epochTimeout'); const epochTimeout = Cypress.env('epochTimeout');
Cypress.Commands.add('wait_for_beginning_of_epoch', () => { export function waitForBeginningOfEpoch() {
cy.contains('Waiting for next epoch to start', epochTimeout).should( cy.contains('Waiting for next epoch to start', epochTimeout).should(
'not.exist' 'not.exist'
); );
cy.contains('Waiting for next epoch to start', epochTimeout).should( cy.contains('Waiting for next epoch to start', epochTimeout).should(
'be.visible' 'be.visible'
); );
}); }
Cypress.Commands.add('staking_validator_page_add_stake', (stake) => { export function stakingValidatorPageAddStake(stake: string) {
cy.highlight(`Adding a stake of ${stake}`); cy.highlight(`Adding a stake of ${stake}`);
cy.get(addStakeRadioButton, epochTimeout).click({ force: true }); cy.get(addStakeRadioButton, epochTimeout).click({ force: true });
cy.get(tokenAmountInputBox).type(stake); cy.get(tokenAmountInputBox).type(stake);
cy.wait_for_beginning_of_epoch(); waitForBeginningOfEpoch();
cy.get(tokenSubmitButton, epochTimeout) cy.get(tokenSubmitButton, epochTimeout)
.should('be.enabled') .should('be.enabled')
.and('contain', `Add ${stake} $VEGA tokens`) .and('contain', `Add ${stake} $VEGA tokens`)
.and('be.visible') .and('be.visible')
.click(); .click();
}); }
Cypress.Commands.add('staking_validator_page_remove_stake', (stake) => { export function stakingValidatorPageRemoveStake(stake: string) {
cy.highlight(`Removing a stake of ${stake}`); cy.highlight(`Removing a stake of ${stake}`);
cy.get(removeStakeRadioButton, epochTimeout).click(); cy.get(removeStakeRadioButton, epochTimeout).click();
cy.get(tokenAmountInputBox).type(stake); cy.get(tokenAmountInputBox).type(stake);
cy.wait_for_beginning_of_epoch(); waitForBeginningOfEpoch();
cy.get(tokenSubmitButton) cy.get(tokenSubmitButton)
.should('be.enabled', epochTimeout) .should('be.enabled', epochTimeout)
.and('contain', `Remove ${stake} $VEGA tokens at the end of epoch`) .and('contain', `Remove ${stake} $VEGA tokens at the end of epoch`)
.and('be.visible') .and('be.visible')
.click(); .click();
cy.get(dialogCloseButton).click(); cy.get(dialogCloseButton).click();
}); }
Cypress.Commands.add('staking_page_associate_tokens', (amount, options) => { export function stakingPageAssociateTokens(
let approve = options && options.approve ? options.approve : false; amount: string,
let type = options && options.type ? options.type : 'wallet'; options?: associateOptions
let skipConfirmation = ) {
const approve = options && options.approve ? options.approve : false;
const type = options && options.type ? options.type : 'wallet';
const skipConfirmation =
options && options.skipConfirmation ? options.skipConfirmation : false; options && options.skipConfirmation ? options.skipConfirmation : false;
cy.highlight(`Associating ${amount} tokens from ${type}`); cy.highlight(`Associating ${amount} tokens from ${type}`);
@ -94,10 +99,13 @@ Cypress.Commands.add('staking_page_associate_tokens', (amount, options) => {
txTimeout txTimeout
).should('be.visible'); ).should('be.visible');
} }
}); }
Cypress.Commands.add('staking_page_disassociate_tokens', (amount, options) => { export function stakingPageDisassociateTokens(
let type = options && options.type ? options.type : 'wallet'; amount: string,
options?: associateOptions
) {
const type = options && options.type ? options.type : 'wallet';
cy.highlight( cy.highlight(
`Disassociating ${amount} tokens via Staking Page back to ${type}` `Disassociating ${amount} tokens via Staking Page back to ${type}`
); );
@ -127,92 +135,89 @@ Cypress.Commands.add('staking_page_disassociate_tokens', (amount, options) => {
txTimeout txTimeout
).should('be.visible'); ).should('be.visible');
} }
}); }
Cypress.Commands.add( export function stakingPageDisassociateAllTokens(type = 'wallet') {
'staking_page_disassociate_all_tokens', cy.highlight(`Disassociating all tokens via Staking Page`);
(type = 'wallet') => { cy.get(ethWalletDissociateButton).first().click();
cy.highlight(`Disassociating all tokens via Staking Page`); cy.get(stakeMaximumTokens, epochTimeout).click();
cy.get(ethWalletDissociateButton).first().click(); cy.get(tokenSubmitButton, epochTimeout).click();
cy.get(stakeMaximumTokens, epochTimeout).click(); if (type === 'wallet') {
cy.get(tokenSubmitButton, epochTimeout).click(); cy.contains(
if (type === 'wallet') { `$VEGA tokens have been returned to Ethereum wallet`,
cy.contains( txTimeout
`$VEGA tokens have been returned to Ethereum wallet`, ).should('be.visible');
txTimeout } else if (type === 'contract') {
).should('be.visible'); cy.contains(
} else if (type === 'contract') { `$VEGA tokens have been returned to Vesting contract`,
cy.contains( txTimeout
`$VEGA tokens have been returned to Vesting contract`, ).should('be.visible');
txTimeout
).should('be.visible');
}
} }
); }
Cypress.Commands.add( export function clickOnValidatorFromList(
'click_on_validator_from_list', validatorNumber: number,
(validatorNumber, validatorName = null) => { validatorName = null
cy.contains('Loading...', epochTimeout).should('not.exist'); ) {
cy.wait_for_beginning_of_epoch(); cy.contains('Loading...', epochTimeout).should('not.exist');
// below is to ensure validator list is shown waitForBeginningOfEpoch();
cy.get(stakeValidatorListName, { timeout: 10000 }).should('exist'); // below is to ensure validator list is shown
cy.get(stakeValidatorListPendingStake, txTimeout).should( cy.get(stakeValidatorListName, { timeout: 10000 }).should('exist');
'not.contain', cy.get(stakeValidatorListPendingStake, txTimeout).should(
'2,000,000,000,000,000,000.00' // number due to bug #936 'not.contain',
'2,000,000,000,000,000,000.00' // number due to bug #936
);
if (validatorName) {
cy.contains(validatorName).click();
} else {
cy.get(`[row-id="${validatorNumber}"]`)
.should('be.visible')
.find(stakeValidatorListName)
.click();
}
}
export function validateValidatorListTotalStakeAndShare(
positionOnList: string,
expectedTotalStake: string,
expectedTotalShare: string
) {
cy.contains('Loading...', epochTimeout).should('not.exist');
waitForBeginningOfEpoch();
cy.get(`[row-id="${positionOnList}"]`).within(() => {
cy.get(stakeValidatorListTotalStake, epochTimeout).should(
'have.text',
expectedTotalStake
); );
if (validatorName) { cy.get(stakeValidatorListTotalShare, epochTimeout).should(
cy.contains(validatorName).click(); 'have.text',
} else { expectedTotalShare
cy.get(`[row-id="${validatorNumber}"]`) );
.should('be.visible') });
.find(stakeValidatorListName) }
.click();
}
}
);
Cypress.Commands.add( export function ensureSpecifiedUnstakedTokensAreAssociated(
'validate_validator_list_total_stake_and_share', tokenAmount: string
(positionOnList, expectedTotalStake, expectedTotalShare) => { ) {
cy.contains('Loading...', epochTimeout).should('not.exist'); cy.highlight(`Ensuring ${tokenAmount} token(s) associated`);
cy.wait_for_beginning_of_epoch(); cy.get(vegaWalletUnstakedBalance)
cy.get(`[row-id="${positionOnList}"]`).within(() => { .children()
cy.get(stakeValidatorListTotalStake, epochTimeout).should( .children()
'have.text', .eq(1)
expectedTotalStake .invoke('text')
); .then((unstakedBalance) => {
cy.get(stakeValidatorListTotalShare, epochTimeout).should( if (parseFloat(unstakedBalance) != parseFloat(tokenAmount)) {
'have.text', vegaWalletTeardown();
expectedTotalShare cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
); '0.00',
txTimeout
);
stakingPageAssociateTokens(tokenAmount);
}
}); });
} }
);
Cypress.Commands.add( export function closeStakingDialog() {
'ensure_specified_unstaked_tokens_are_associated',
(tokenAmount) => {
cy.highlight(`Ensuring ${tokenAmount} token(s) associated`);
cy.get(vegaWalletUnstakedBalance)
.children()
.children()
.eq(1)
.invoke('text')
.then((unstakedBalance) => {
if (parseFloat(unstakedBalance) != parseFloat(tokenAmount)) {
cy.vega_wallet_teardown();
cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
'0.00',
txTimeout
);
cy.staking_page_associate_tokens(tokenAmount);
}
});
}
);
Cypress.Commands.add('close_staking_dialog', () => {
cy.getByTestId('dialog-title').should( cy.getByTestId('dialog-title').should(
'contain.text', 'contain.text',
'At the beginning of the next epoch' 'At the beginning of the next epoch'
@ -220,20 +225,26 @@ Cypress.Commands.add('close_staking_dialog', () => {
cy.getByTestId('dialog-content').within(() => { cy.getByTestId('dialog-content').within(() => {
cy.get('a').should('have.text', 'Back to Staking').click(); cy.get('a').should('have.text', 'Back to Staking').click();
}); });
}); }
Cypress.Commands.add( export function validateWalletCurrency(
'validate_wallet_currency', currencyTitle: string,
(currencyTitle, expectedAmount) => { expectedAmount: string
cy.get("[data-testid='currency-title']") ) {
.contains(currencyTitle) cy.get("[data-testid='currency-title']")
.parent() .contains(currencyTitle)
.parent() .parent()
.within(() => { .parent()
cy.getByTestId('currency-value', txTimeout).should( .within(() => {
'have.text', cy.getByTestId('currency-value', txTimeout).should(
expectedAmount 'have.text',
); expectedAmount
}); );
} });
); }
interface associateOptions {
approve?: boolean;
type?: string;
skipConfirmation?: boolean;
}

View File

@ -3,7 +3,7 @@ const connectToEthButton =
'[data-testid="connect-to-eth-wallet-button"]:visible'; '[data-testid="connect-to-eth-wallet-button"]:visible';
const capsuleWalletConnectButton = '[data-testid="web3-connector-Unknown"]'; const capsuleWalletConnectButton = '[data-testid="web3-connector-Unknown"]';
Cypress.Commands.add('ethereum_wallet_connect', () => { export function ethereumWalletConnect() {
cy.highlight('Connecting Eth Wallet'); cy.highlight('Connecting Eth Wallet');
cy.get(connectToEthButton).within(() => { cy.get(connectToEthButton).within(() => {
cy.contains('Connect Ethereum wallet to associate $VEGA') cy.contains('Connect Ethereum wallet to associate $VEGA')
@ -20,4 +20,4 @@ Cypress.Commands.add('ethereum_wallet_connect', () => {
// It needs a few seconds before becoming operational // It needs a few seconds before becoming operational
// eslint-disable-next-line cypress/no-unnecessary-waiting // eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(4000); cy.wait(4000);
}); }

View File

@ -1,197 +0,0 @@
import {
StakingBridge,
Token,
TokenVesting,
TokenFaucetable,
CollateralBridge,
} from '@vegaprotocol/smart-contracts';
import { ethers, Wallet } from 'ethers';
const vegaWalletContainer = 'aside [data-testid="vega-wallet"]';
const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic');
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
const vegaTokenAddress = Cypress.env('vegaTokenAddress');
const ethWalletPubKey = Cypress.env('ethWalletPublicKey');
const ethStakingBridgeContractAddress = Cypress.env(
'ethStakingBridgeContractAddress'
);
const ethProviderUrl = Cypress.env('ethProviderUrl');
const getAccount = (number = 0) => `m/44'/60'/0'/0/${number}`;
const transactionTimeout = '90000';
const Erc20BridgeAddress = '0x9708FF7510D4A7B9541e1699d15b53Ecb1AFDc54';
before('Vega wallet teardown prep', function () {
cy.wrap(new ethers.providers.JsonRpcProvider({ url: ethProviderUrl }), {
log: false,
}).as('provider');
cy.wrap(Wallet.fromMnemonic(vegaWalletMnemonic, getAccount(0)).privateKey, {
log: false,
}).then((privateKey) => {
cy.wrap(new Wallet(privateKey, this.provider), { log: false }).as('signer');
});
cy.get('@signer', { log: false }).then((signer) => {
cy.wrap(new StakingBridge(ethStakingBridgeContractAddress, signer), {
log: false,
}).as('stakingBridgeContract');
cy.wrap(new TokenVesting(vegaTokenContractAddress, signer), {
log: false,
}).as('vestingContract');
});
});
beforeEach(function () {
cy.wrap(this.stakingBridgeContract).as('stakingBridgeContract');
cy.wrap(this.vestingContract).as('vestingContract');
});
Cypress.Commands.add('deposit_asset', function (assetEthAddress, amount) {
cy.highlight('Depositing asset into vegawallet');
cy.get('@signer', { log: false }).then((signer) => {
// Approve asset
cy.wrap(
new TokenFaucetable(assetEthAddress, signer).approve(
Erc20BridgeAddress,
amount + '0'.repeat(19)
)
)
.then((tx) => {
cy.wait_for_transaction(tx);
})
.then(() => {
cy.wrap(new CollateralBridge(Erc20BridgeAddress, signer), {
log: false,
}).then((bridge) => {
// Deposit asset into vega wallet
cy.wrap(
bridge.deposit_asset(
assetEthAddress,
amount + '0'.repeat(18),
'0x' + vegaWalletPubKey
),
{ timeout: transactionTimeout, log: false }
).then((tx) => {
cy.wait_for_transaction(tx);
});
});
});
});
});
Cypress.Commands.add('faucet_asset', function (assetEthAddress) {
cy.get('@signer', { log: false }).then((signer) => {
cy.wrap(new TokenFaucetable(assetEthAddress, signer), { log: false }).then(
(token) => {
cy.wrap(token.faucet(), {
timeout: transactionTimeout,
log: false,
}).then((tx) => {
cy.wait_for_transaction(tx);
});
}
);
});
});
Cypress.Commands.add('vega_wallet_teardown', function () {
cy.get('aside [data-testid="associated-amount"]')
.should('be.visible')
.invoke('text')
.as('associatedAmount');
cy.get('body').then(($body) => {
if (
$body.find('[data-testid="eth-wallet-associated-balances"]').length ||
this.associatedAmount != '0.00'
) {
cy.vega_wallet_teardown_vesting(this.vestingContract);
cy.vega_wallet_teardown_staking(this.stakingBridgeContract);
}
});
cy.get(vegaWalletContainer).within(() => {
cy.get('[data-testid="vega-wallet-balance-unstaked"]', {
timeout: 30000,
}).should('contain.text', '0.00');
});
});
Cypress.Commands.add(
'vega_wallet_set_specified_approval_amount',
function (resetAmount) {
cy.highlight(`Setting token approval amount to ${resetAmount}`);
cy.wrap(new Token(vegaTokenAddress, this.signer), { log: false }).then(
(token) => {
cy.wrap(
token.approve(
ethStakingBridgeContractAddress,
resetAmount.concat('000000000000000000')
),
{ 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.stake_balance(ethWalletPubKey, vegaWalletPubKey),
{
timeout: transactionTimeout,
log: false,
}
).then((stake_amount) => {
if (String(stake_amount) != '0') {
cy.wrap(
stakingBridgeContract.remove_stake(stake_amount, vegaWalletPubKey),
{ timeout: transactionTimeout, log: false }
).then((tx) => {
cy.wait_for_transaction(tx);
});
}
});
}
);
Cypress.Commands.add('vega_wallet_teardown_vesting', (vestingContract) => {
cy.highlight('Tearing down vesting tokens from vega wallet if present');
cy.wrap(vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey), {
timeout: transactionTimeout,
log: false,
}).then((vesting_amount) => {
if (String(vesting_amount) != '0') {
cy.wrap(vestingContract.remove_stake(vesting_amount, vegaWalletPubKey), {
timeout: transactionTimeout,
log: false,
}).then((tx) => {
cy.wait_for_transaction(tx);
});
}
});
});
Cypress.Commands.add('vega_wallet_associate', (amount) => {
amount = amount + '0'.repeat(18);
cy.highlight('Associating tokens');
cy.get('@stakingBridgeContract').then((stakingBridgeContract) => {
stakingBridgeContract.stake(amount, vegaWalletPubKey);
});
});
Cypress.Commands.add('vega_wallet_disassociate', (amount) => {
amount = amount + '0'.repeat(18);
cy.highlight('Disassociating tokens');
cy.get('@stakingBridgeContract').then((stakingBridgeContract) => {
stakingBridgeContract.remove_stake(amount, vegaWalletPubKey);
});
});
Cypress.Commands.add('wait_for_transaction', (tx) => {
cy.wrap(tx.wait(1).catch(cy.log), { timeout: transactionTimeout });
});

View File

@ -0,0 +1,146 @@
import { promiseWithTimeout } from '@vegaprotocol/cypress';
import {
StakingBridge,
Token,
TokenVesting,
TokenFaucetable,
CollateralBridge,
} from '@vegaprotocol/smart-contracts';
import { ethers, Wallet } from 'ethers';
const vegaWalletContainer = 'aside [data-testid="vega-wallet"]';
const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic');
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
const vegaTokenAddress = Cypress.env('vegaTokenAddress');
const ethWalletPubKey = Cypress.env('ethWalletPublicKey');
const ethStakingBridgeContractAddress = Cypress.env(
'ethStakingBridgeContractAddress'
);
const ethProviderUrl = Cypress.env('ethProviderUrl');
const getAccount = (number = 0) => `m/44'/60'/0'/0/${number}`;
const transactionTimeout = 100000;
const Erc20BridgeAddress = '0x9708FF7510D4A7B9541e1699d15b53Ecb1AFDc54';
const provider = new ethers.providers.JsonRpcProvider({ url: ethProviderUrl });
const privateKey = Wallet.fromMnemonic(
vegaWalletMnemonic,
getAccount(0)
).privateKey;
const signer = new Wallet(privateKey, provider);
const stakingBridgeContract = new StakingBridge(
ethStakingBridgeContractAddress,
signer
);
const vestingContract = new TokenVesting(vegaTokenContractAddress, signer);
export async function depositAsset(assetEthAddress: string, amount: string) {
// Approve asset
const faucet = new TokenFaucetable(assetEthAddress, signer);
cy.wrap(faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(19)), {
timeout: transactionTimeout,
log: false,
}).then(() => {
const collateralBridge = new CollateralBridge(Erc20BridgeAddress, signer);
cy.wrap(
collateralBridge.deposit_asset(
assetEthAddress,
amount + '0'.repeat(18),
'0x' + vegaWalletPubKey
),
{ timeout: transactionTimeout, log: false }
);
});
}
export async function faucetAsset(assetEthAddress: string) {
const faucet = new TokenFaucetable(assetEthAddress, signer);
await promiseWithTimeout(faucet.faucet(), 10 * 60 * 1000, 'faucet asset');
}
export async function vegaWalletTeardown() {
cy.get('[data-testid="associated-amount"]')
.should('be.visible')
.invoke('text')
.then((associatedAmount) => {
cy.get('body').then(($body) => {
if (
$body.find('[data-testid="eth-wallet-associated-balances"]').length ||
associatedAmount != '0.00'
) {
vegaWalletTeardownVesting(vestingContract);
vegaWalletTeardownStaking(stakingBridgeContract);
}
});
cy.get(vegaWalletContainer).within(() => {
cy.getByTestId('vega-wallet-balance-staked-validators', {
timeout: transactionTimeout,
}).should('not.exist');
cy.getByTestId('associated-amount', {
timeout: transactionTimeout,
}).contains('0.00', {
timeout: transactionTimeout,
});
});
});
}
export async function vegaWalletSetSpecifiedApprovalAmount(
resetAmount: string
) {
cy.highlight(`Setting token approval amount to ${resetAmount}`);
const token = new Token(vegaTokenAddress, signer);
await promiseWithTimeout(
token.approve(
ethStakingBridgeContractAddress,
resetAmount.concat('000000000000000000')
),
10 * 60 * 1000,
'set approval amount'
);
}
async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
cy.highlight('Tearing down staking tokens from vega wallet if present');
cy.wrap(
stakingBridgeContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
{ timeout: transactionTimeout, log: false }
).then((stakeBalance) => {
if (Number(stakeBalance) != 0) {
cy.wrap(
stakingBridgeContract.remove_stake(
String(stakeBalance),
vegaWalletPubKey
),
{ timeout: transactionTimeout, log: false }
);
}
});
}
async function vegaWalletTeardownVesting(vestingContract: TokenVesting) {
cy.highlight('Tearing down vesting tokens from vega wallet if present');
cy.wrap(vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey), {
timeout: transactionTimeout,
log: false,
}).then((vestingAmount) => {
if (Number(vestingAmount) != 0) {
cy.wrap(
vestingContract.remove_stake(String(vestingAmount), vegaWalletPubKey),
{ timeout: transactionTimeout, log: false }
);
}
});
}
export async function vegaWalletAssociate(amount: string) {
cy.highlight('Associating tokens');
amount = amount + '0'.repeat(18);
stakingBridgeContract.stake(amount, vegaWalletPubKey);
}
export async function vegaWalletDisassociate(amount: string) {
cy.highlight('Disassociating tokens');
amount = amount + '0'.repeat(18);
stakingBridgeContract.remove_stake(amount, vegaWalletPubKey);
}

View File

@ -1,17 +0,0 @@
Cypress.Commands.add(
'vega_wallet_faucet_assets_without_check',
function (asset, amount, vegaWalletPublicKey) {
cy.highlight(`Topping up vega wallet with ${asset}, amount: ${amount}`);
cy.exec(
`curl -X POST -d '{"amount": "${amount}", "asset": "${asset}", "party": "${vegaWalletPublicKey}"}' http://localhost:1790/api/v1/mint`
)
.its('stdout')
.then((response) => {
assert.include(
response,
`"success":true`,
'Ensuring curl command was successfully undertaken'
);
});
}
);

View File

@ -0,0 +1,18 @@
export function vegaWalletFaucetAssetsWithoutCheck(
asset: string,
amount: string,
vegaWalletPublicKey: string
) {
cy.highlight(`Topping up vega wallet with ${asset}, amount: ${amount}`);
cy.exec(
`curl -X POST -d '{"amount": "${amount}", "asset": "${asset}", "party": "${vegaWalletPublicKey}"}' http://localhost:1790/api/v1/mint`
)
.its('stdout')
.then((response) => {
assert.include(
response,
`"success":true`,
'Ensuring curl command was successfully undertaken'
);
});
}

View File

@ -1,6 +1,8 @@
{ {
"extends": "../../tsconfig.base.json", "extends": "../../tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"target": "es5",
"lib": ["es5", "dom", "es2021"],
"strict": true, "strict": true,
"jsx": "react-jsx", "jsx": "react-jsx",
"sourceMap": false, "sourceMap": false,

View File

@ -165,7 +165,7 @@ const ConnectedKey = () => {
</section> </section>
<WalletCardActions> <WalletCardActions>
<Link className="flex-1" to={Routes.ASSOCIATE}> <Link className="flex-1" to={Routes.ASSOCIATE}>
<Button size="sm" fill={true}> <Button data-testid="associate-btn" size="sm" fill={true}>
{t('associate')} {t('associate')}
</Button> </Button>
</Link> </Link>

View File

@ -22,6 +22,8 @@ import { addVegaWalletSubmitProposal } from './lib/commands/vega-wallet-submit-p
import { addGetNodes } from './lib/commands/get-nodes'; import { addGetNodes } from './lib/commands/get-nodes';
import { addVegaWalletSubmitLiquidityProvision } from './lib/commands/vega-wallet-submit-liquidity-provision'; import { addVegaWalletSubmitLiquidityProvision } from './lib/commands/vega-wallet-submit-liquidity-provision';
import { addImportNodeWallets } from './lib/commands/import-node-wallets'; import { addImportNodeWallets } from './lib/commands/import-node-wallets';
import { addVegaWalletTopUpRewardsPool } from './lib/commands/vega-wallet-top-up-rewards-pool';
import { addAssociateTokensToVegaWallet } from './lib/commands/associate-tokens-to-vega-wallet';
addGetTestIdcommand(); addGetTestIdcommand();
addSlackCommand(); addSlackCommand();
@ -45,6 +47,8 @@ addValidatorsSelfDelegate();
addVegaWalletSubmitProposal(); addVegaWalletSubmitProposal();
addVegaWalletSubmitLiquidityProvision(); addVegaWalletSubmitLiquidityProvision();
addImportNodeWallets(); addImportNodeWallets();
addVegaWalletTopUpRewardsPool();
addAssociateTokensToVegaWallet();
export { export {
mockConnectWallet, mockConnectWallet,

View File

@ -34,7 +34,7 @@ export async function stakeForVegaPublicKey(
ethereumConfig.staking_bridge_contract.address, ethereumConfig.staking_bridge_contract.address,
amount + '0'.repeat(19) amount + '0'.repeat(19)
), ),
1000, 10 * 60 * 1000,
'approve staking tx' 'approve staking tx'
); );

View File

@ -3,7 +3,7 @@ declare global {
namespace Cypress { namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> { interface Chainable<Subject> {
updateCapsuleMultiSig(): void; updateCapsuleMultiSig(): Chainable<Subject>;
} }
} }
} }

View File

@ -0,0 +1,33 @@
import { stakeForVegaPublicKey } from '../capsule/ethereum-setup';
import { createEthereumWallet } from '../capsule/ethereum-wallet';
import { setGraphQLEndpoint } from '../capsule/request';
import { createWalletClient } from '../capsule/wallet-client';
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
associateTokensToVegaWallet(amount: string): void;
}
}
}
export function addAssociateTokensToVegaWallet() {
Cypress.Commands.add('associateTokensToVegaWallet', (amount) => {
const ethWalletMnemonic = Cypress.env('ETH_WALLET_MNEMONIC');
const ethereumProviderUrl = Cypress.env('ETHEREUM_PROVIDER_URL');
const vegaWalletUrl = Cypress.env('VEGA_WALLET_URL');
const vegaUrl = Cypress.env('VEGA_URL');
const vegaPubKey = Cypress.env('VEGA_PUBLIC_KEY');
const apiToken = Cypress.env('VEGA_WALLET_API_TOKEN');
setGraphQLEndpoint(vegaUrl);
createWalletClient(vegaWalletUrl, apiToken);
createEthereumWallet(ethWalletMnemonic, ethereumProviderUrl);
cy.highlight('Perform Eth tx at start of test');
cy.wrap(stakeForVegaPublicKey(vegaPubKey, amount), { timeout: 60000 });
});
}

View File

@ -3,7 +3,7 @@ declare global {
namespace Cypress { namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> { interface Chainable<Subject> {
contains_exactly(expected_result: string): void; contains_exactly(expected_result: string): Chainable<Subject>;
} }
} }
} }

View File

@ -3,7 +3,7 @@ declare global {
namespace Cypress { namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> { interface Chainable<Subject> {
get_network_parameters(): void; get_network_parameters(): Chainable<networkParameters>;
} }
} }
} }
@ -38,7 +38,126 @@ export function addGetNetworkParameters() {
r[key] = value; r[key] = value;
return r; return r;
}, {}); }, {});
return object; return cy.wrap(object);
}); });
}); });
} }
interface networkParameters {
'blockchains.ethereumConfig': string;
'governance.proposal.asset.maxClose': string;
'governance.proposal.asset.maxEnact': string;
'governance.proposal.asset.minClose': string;
'governance.proposal.asset.minEnact': string;
'governance.proposal.asset.minProposerBalance': string;
'governance.proposal.asset.minVoterBalance': string;
'governance.proposal.asset.requiredMajority': string;
'governance.proposal.asset.requiredParticipation': string;
'governance.proposal.freeform.maxClose': string;
'governance.proposal.freeform.minClose': string;
'governance.proposal.freeform.minProposerBalance': string;
'governance.proposal.freeform.minVoterBalance': string;
'governance.proposal.freeform.requiredMajority': string;
'governance.proposal.freeform.requiredParticipation': string;
'governance.proposal.market.maxClose': string;
'governance.proposal.market.maxEnact': string;
'governance.proposal.market.minClose': string;
'governance.proposal.market.minEnact': string;
'governance.proposal.market.minProposerBalance': string;
'governance.proposal.market.minVoterBalance': string;
'governance.proposal.market.requiredMajority': string;
'governance.proposal.market.requiredParticipation': string;
'governance.proposal.updateAsset.maxClose': string;
'governance.proposal.updateAsset.maxEnact': string;
'governance.proposal.updateAsset.minClose': string;
'governance.proposal.updateAsset.minEnact': string;
'governance.proposal.updateAsset.minProposerBalance': string;
'governance.proposal.updateAsset.minVoterBalance': string;
'governance.proposal.updateAsset.requiredMajority': string;
'governance.proposal.updateAsset.requiredParticipation': string;
'governance.proposal.updateMarket.maxClose': string;
'governance.proposal.updateMarket.maxEnact': string;
'governance.proposal.updateMarket.minClose': string;
'governance.proposal.updateMarket.minEnact': string;
'governance.proposal.updateMarket.minProposerBalance': string;
'governance.proposal.updateMarket.minProposerEquityLikeShare': string;
'governance.proposal.updateMarket.minVoterBalance': string;
'governance.proposal.updateMarket.requiredMajority': string;
'governance.proposal.updateMarket.requiredMajorityLP': string;
'governance.proposal.updateMarket.requiredParticipation': string;
'governance.proposal.updateMarket.requiredParticipationLP': string;
'governance.proposal.updateNetParam.maxClose': string;
'governance.proposal.updateNetParam.maxEnact': string;
'governance.proposal.updateNetParam.minClose': string;
'governance.proposal.updateNetParam.minEnact': string;
'governance.proposal.updateNetParam.minProposerBalance': string;
'governance.proposal.updateNetParam.minVoterBalance': string;
'governance.proposal.updateNetParam.requiredMajority': string;
'governance.proposal.updateNetParam.requiredParticipation': string;
'limits.assets.proposeEnabledFrom': string;
'limits.markets.maxPeggedOrders': string;
'limits.markets.proposeEnabledFrom': string;
'market.auction.maximumDuration': string;
'market.auction.minimumDuration': string;
'market.fee.factors.infrastructureFee': string;
'market.fee.factors.makerFee': string;
'market.liquidity.bondPenaltyParameter': string;
'market.liquidity.maximumLiquidityFeeFactorLevel': string;
'market.liquidity.minimum.probabilityOfTrading.lpOrders': string;
'market.liquidity.probabilityOfTrading.tau.scaling': string;
'market.liquidity.providers.fee.distributionTimeStep': string;
'market.liquidity.stakeToCcyVolume': string;
'market.liquidity.targetstake.triggering.ratio': string;
'market.liquidityProvision.minLpStakeQuantumMultiple': string;
'market.liquidityProvision.shapes.maxSize': string;
'market.margin.scalingFactors': string;
'market.monitor.price.defaultParameters': string;
'market.stake.target.scalingFactor': string;
'market.stake.target.timeWindow': string;
'market.value.windowLength': string;
'network.checkpoint.timeElapsedBetweenCheckpoints': string;
'network.floatingPointUpdates.delay': string;
'network.markPriceUpdateMaximumFrequency': string;
'network.transaction.defaultgas': string;
'network.transactions.maxgasperblock': string;
'network.transactions.minBlockCapacity': string;
'network.validators.ersatz.multipleOfTendermintValidators': string;
'network.validators.ersatz.rewardFactor': string;
'network.validators.incumbentBonus': string;
'network.validators.minimumEthereumEventsForNewValidator': string;
'network.validators.multisig.numberOfSigners': string;
'network.validators.tendermint.number': string;
'reward.asset': string;
'reward.staking.delegation.competitionLevel': string;
'reward.staking.delegation.delegatorShare': string;
'reward.staking.delegation.maxPayoutPerEpoch': string;
'reward.staking.delegation.maxPayoutPerParticipant': string;
'reward.staking.delegation.minValidators': string;
'reward.staking.delegation.minimumValidatorStake': string;
'reward.staking.delegation.optimalStakeMultiplier': string;
'reward.staking.delegation.payoutDelay': string;
'reward.staking.delegation.payoutFraction': string;
'rewards.marketCreationQuantumMultiple': string;
'snapshot.interval.length': string;
'spam.pow.difficulty': string;
'spam.pow.hashFunction': string;
'spam.pow.increaseDifficulty': string;
'spam.pow.numberOfPastBlocks': string;
'spam.pow.numberOfTxPerBlock': string;
'spam.protection.delegation.min.tokens': string;
'spam.protection.max.batchSize': string;
'spam.protection.max.delegations': string;
'spam.protection.max.proposals': string;
'spam.protection.max.votes': string;
'spam.protection.maxUserTransfersPerEpoch': string;
'spam.protection.minMultisigUpdates': string;
'spam.protection.minimumWithdrawalQuantumMultiple': string;
'spam.protection.proposal.min.tokens': string;
'spam.protection.voting.min.tokens': string;
'transfer.fee.factor': string;
'transfer.minTransferQuantumMultiple': string;
'validator.performance.scaling.factor': string;
'validators.delegation.minAmount': string;
'validators.epoch.length': string;
'validators.vote.required': string;
}

View File

@ -21,10 +21,10 @@ export function addVegaWalletReceiveFaucetedAsset() {
`Topping up vega wallet with ${assetName}, amount: ${amount}` `Topping up vega wallet with ${assetName}, amount: ${amount}`
); );
// @ts-ignore - ignoring Cypress type error which gets resolved when Cypress uses the command // @ts-ignore - ignoring Cypress type error which gets resolved when Cypress uses the command
cy.getAssets().then((assets) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any
console.log(assets); cy.getAssets().then((assets: any) => {
const asset = assets.find((a) => a.name === assetName); const asset = assets[assetName];
if (asset) { if (assets[assetName] !== undefined) {
for (let i = 0; i < asset.decimals; i++) amount += '0'; for (let i = 0; i < asset.decimals; i++) amount += '0';
cy.exec( cy.exec(
`curl -X POST -d '{"amount": "${amount}", "asset": "${asset.id}", "party": "${vegaWalletPublicKey}"}' http://localhost:1790/api/v1/mint` `curl -X POST -d '{"amount": "${amount}", "asset": "${asset.id}", "party": "${vegaWalletPublicKey}"}' http://localhost:1790/api/v1/mint`
@ -38,7 +38,10 @@ export function addVegaWalletReceiveFaucetedAsset() {
); );
}); });
} else { } else {
const validAssets = assets.filter((a) => a.name.includes('fake')); // eslint-disable-next-line @typescript-eslint/no-explicit-any
const validAssets = assets.filter((a: any) =>
a.name.includes('fake')
);
assert.exists( assert.exists(
asset, asset,
`${assetName} is not a faucet-able asset, only the following assets can be faucet-ed: ${validAssets}` `${assetName} is not a faucet-able asset, only the following assets can be faucet-ed: ${validAssets}`

View File

@ -0,0 +1,50 @@
import { AccountType } from '@vegaprotocol/types';
import type { TransferBody } from '@vegaprotocol/wallet';
import { createWalletClient, sendVegaTx } from '../capsule/wallet-client';
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
VegaWalletTopUpRewardsPool(
transferStartEpoch: number,
transferEndEpoch: number
): void;
}
}
}
export function addVegaWalletTopUpRewardsPool() {
Cypress.Commands.add(
'VegaWalletTopUpRewardsPool',
(transferStartEpoch, transferEndEpoch) => {
const vegaWalletUrl = Cypress.env('VEGA_WALLET_URL');
const token = Cypress.env('VEGA_WALLET_API_TOKEN');
const vegaPubKey = Cypress.env('VEGA_PUBLIC_KEY');
const assetAddress =
'b4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b';
createWalletClient(vegaWalletUrl, token);
const transactionBody: TransferBody = {
transfer: {
fromAccountType: AccountType.ACCOUNT_TYPE_GENERAL,
toAccountType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
to: '0000000000000000000000000000000000000000000000000000000000000000',
asset: assetAddress,
amount: '1000000000000000000',
recurring: {
factor: '1',
startEpoch: transferStartEpoch,
endEpoch: transferEndEpoch,
},
},
};
cy.highlight('Topping up rewards pool');
sendVegaTx(vegaPubKey, transactionBody);
}
);
}

View File

@ -37,7 +37,7 @@ GatewayEnabled = true
Port = {{add 210 .NodeNumber}}2 Port = {{add 210 .NodeNumber}}2
Enabled = false Enabled = false
[Broker] [Broker]
Level = "Info" Level = "Debug"
UseEventFile = false UseEventFile = false
[Broker.SocketConfig] [Broker.SocketConfig]
Port = {{add 300 .NodeNumber}}5 Port = {{add 300 .NodeNumber}}5
@ -54,6 +54,7 @@ GatewayEnabled = true
{{- end -}}] {{- end -}}]
UseIpfsDefaultPeers = false UseIpfsDefaultPeers = false
SwarmPort = 40{{.NodeNumber}}5 SwarmPort = {{add 400 .NodeNumber}}5
StartWebUI = false StartWebUI = false
WebUIPort = 50{{.NodeNumber}}5 WebUIPort = {{add 500 .NodeNumber}}5
SwarmKeyOverride = "{{ .NodeSet.DataNode.UniqueSwarmKey }}"

View File

@ -60,6 +60,7 @@ GatewayEnabled = true
SwarmPort = {{add 400 .NodeNumber}}5 SwarmPort = {{add 400 .NodeNumber}}5
StartWebUI = false StartWebUI = false
WebUIPort = {{add 500 .NodeNumber}}5 WebUIPort = {{add 500 .NodeNumber}}5
SwarmKeyOverride = "{{ .NodeSet.DataNode.UniqueSwarmKey }}"
[NetworkHistory.Snapshot] [NetworkHistory.Snapshot]
PanicOnSnapshotCreationError = true PanicOnSnapshotCreationError = true
WaitForCreationLockTimeout = "5s" WaitForCreationLockTimeout = "5s"

View File

@ -1,29 +1,35 @@
log_level = "info" log_level = "info"
proxy_app = "tcp://127.0.0.1:{{add 2660 .NodeNumber}}8" proxy_app = "tcp://127.0.0.1:26{{ printf "%02d" (add .NodeNumber 60) }}8"
moniker = "{{.TendermintNodePrefix}}-{{.NodeNumber}}" moniker = "{{.TendermintNodePrefix}}-{{.NodeNumber}}"
[rpc] [rpc]
laddr = "tcp://0.0.0.0:{{add 2660 .NodeNumber}}7" laddr = "tcp://0.0.0.0:26{{ printf "%02d" (add .NodeNumber 60) }}7"
unsafe = true unsafe = true
cors_allowed_origins = ["*"]
cors_allowed_methods = ["HEAD", "GET", "POST", ]
cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ]
[p2p] [p2p]
laddr = "tcp://0.0.0.0:{{add 2660 .NodeNumber}}6" laddr = "tcp://0.0.0.0:26{{ printf "%02d" (add .NodeNumber 60) }}6"
addr_book_strict = false addr_book_strict = false
max_packet_msg_payload_size = 4096 max_packet_msg_payload_size = 4096
pex = false pex = false
allow_duplicate_ip = true allow_duplicate_ip = true
persistent_peers = "{{- range $i, $peer := .NodePeers -}} persistent_peers = "{{- range $i, $peer := .NodePeers -}}
{{- if ne $i 0 }},{{end -}} {{- if ne $i 0 }},{{end -}}
{{- $peer.ID}}@127.0.0.1:{{add 2660 $peer.Index}}6 {{- $peer.ID}}@127.0.0.1:26{{ printf "%02d" (add $peer.Index 60) }}6
{{- end -}}" {{- end -}}"
persistent_peers_max_dial_period = "5s"
[mempool] [mempool]
size = 10000 size = 10000
cache_size = 20000 cache_size = 20000
[consensus] [consensus]
skip_timeout_commit = true skip_timeout_commit = true
[statesync]
enable = false
rpc_servers = "{{- range $i, $peer := .NodePeers -}}
{{- if ne $i 0 }},{{end -}}
127.0.0.1:26{{ printf "%02d" (add $peer.Index 60) }}7
{{- end -}}"

View File

@ -1,32 +1,133 @@
[Admin] [Admin]
[Admin.Server] [Admin.Server]
SocketPath = "/tmp/vega-{{.NodeNumber}}.sock" SocketPath = "{{.NodeHomeDir}}/vega.sock"
Enabled = true Enabled = true
[API] [API]
Port = {{add 300 .NodeNumber}}2 Level = "Info"
Port = 3{{ printf "%02d" .NodeNumber }}2
[API.REST] [API.REST]
Port = {{add 300 .NodeNumber}}3 Port = 3{{ printf "%02d" .NodeNumber }}3
[Blockchain] [Blockchain]
Level = "Info"
[Blockchain.Tendermint] [Blockchain.Tendermint]
RPCAddr = "tcp://127.0.0.1:{{add 2660 .NodeNumber}}7" Level = "Info"
RPCAddr = "tcp://127.0.0.1:26{{ printf "%02d" (add .NodeNumber 60) }}7"
[Blockchain.Null] [Blockchain.Null]
Port = {{add 310 .NodeNumber}}1 Level = "Info"
Port = 3{{ printf "%02d" (add .NodeNumber 10) }}1
[Collateral]
Level = "Info"
[CoreAPI]
LogLevel = "Info"
[Execution]
Level = "Info"
[Execution.Matching]
Level = "Info"
[Execution.Risk]
Level = "Info"
[Execution.Position]
Level = "Info"
LogPositionUpdate = true
[Execution.Settlement]
Level = "Info"
[Execution.Fee]
Level = "Info"
[Execution.Liquidity]
Level = "Info"
[EvtForward] [EvtForward]
Level = "Info" Level = "Info"
RetryRate = "1s" RetryRate = "1s"
[EvtForward.Ethereum]
Level = "Info"
[Ethereum] [Ethereum]
RPCEndpoint = "{{.ETHEndpoint}}" RPCEndpoint = "{{.ETHEndpoint}}"
[NodeWallet]
Level = "Info"
[NodeWallet.ETH]
Level = "Info"
[Processor] [Processor]
Level = "Info"
[Processor.Ratelimit] [Processor.Ratelimit]
Requests = 10000 Requests = 10000
PerNBlocks = 1 PerNBlocks = 1
[Oracles]
Level = "Info"
[Time]
Level = "Info"
[Epoch]
Level = "Info"
[Monitoring]
Level = "Info"
[Metrics]
Level = "Info"
[Governance]
Level = "Info"
[Assets]
Level = "Info"
[Notary]
Level = "Info"
[Genesis]
Level = "Info"
[Validators]
Level = "Info"
[Banking]
Level = "Info"
[Stats]
Level = "Info"
[NetworkParameters]
Level = "Info"
[Limits]
Level = "Info"
[Checkpoint]
Level = "Info"
[Staking]
Level = "Info"
[Broker] [Broker]
[Broker.Socket] Level = "Info"
Port = {{add 300 .NodeNumber}}5 [Broker.Socket]
Enabled = true Port = 3{{ printf "%02d" .NodeNumber }}5
Enabled = true
[Rewards]
Level = "Info"
[Delegation]
Level = "Info"
[Spam]
Level = "Info"
[Snapshot]
Level = "Info"
[StateVar]
Level = "Info"
[Pprof]
Level = "Info"