From 2533e5ec44dd0546a678fe9589f203434acc0bf2 Mon Sep 17 00:00:00 2001 From: Joe Tsang <30622993+jtsang586@users.noreply.github.com> Date: Fri, 19 May 2023 14:29:20 +0100 Subject: [PATCH] test(governance): 3790 proposal tests refactor (#3838) --- .../fixtures/proposals/new-market-raw.json | 113 ++++++++++++++++ .../integration/flow/proposal-details.cy.ts | 91 +++++++------ .../integration/flow/proposal-enacted.cy.ts | 34 ++--- .../src/integration/flow/proposal-flow.cy.ts | 58 ++++---- .../src/integration/flow/proposal-forms.cy.ts | 13 +- .../src/integration/flow/proposal-list.cy.ts | 96 ++++++------- .../src/integration/flow/staking-flow.cy.ts | 31 ++--- .../flow/token-association-flow.cy.ts | 15 ++- .../integration/flow/withdrawal-flow.cy.ts | 7 +- .../src/integration/view/pubkey-view.cy.ts | 3 +- .../src/support/governance.functions.ts | 90 ++++++++++--- .../src/support/proposal.functions.ts | 126 ++++++++++++++++++ .../src/support/wallet-teardown.functions.ts | 9 +- 13 files changed, 471 insertions(+), 215 deletions(-) create mode 100644 apps/governance-e2e/src/fixtures/proposals/new-market-raw.json diff --git a/apps/governance-e2e/src/fixtures/proposals/new-market-raw.json b/apps/governance-e2e/src/fixtures/proposals/new-market-raw.json new file mode 100644 index 000000000..8f7efbe4d --- /dev/null +++ b/apps/governance-e2e/src/fixtures/proposals/new-market-raw.json @@ -0,0 +1,113 @@ +{ + "rationale": { + "title": "New Market Proposal E2E submission", + "description": "E2E new market proposal" + }, + "terms": { + "newMarket": { + "changes": { + "decimalPlaces": "5", + "positionDecimalPlaces": "5", + "linearSlippageFactor": "0.001", + "quadraticSlippageFactor": "0", + "lpPriceRange": "10", + "instrument": { + "name": "Token test market", + "code": "TEST.24h", + "future": { + "settlementAsset": "73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0", + "quoteName": "fBTC", + "dataSourceSpecForSettlementData": { + "external": { + "oracle": { + "signers": [ + { + "pubKey": { + "key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680" + } + } + ], + "filters": [ + { + "key": { + "name": "prices.ETH.value", + "type": "TYPE_INTEGER", + "numberDecimalPlaces": "0" + }, + "conditions": [ + { + "operator": "OPERATOR_GREATER_THAN", + "value": "0" + } + ] + } + ] + } + } + }, + "dataSourceSpecForTradingTermination": { + "external": { + "oracle": { + "signers": [ + { + "pubKey": { + "key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680" + } + } + ], + "filters": [ + { + "key": { + "name": "trading.terminated.ETH5", + "type": "TYPE_BOOLEAN" + }, + "conditions": [ + { + "operator": "OPERATOR_EQUALS", + "value": "true" + } + ] + } + ] + } + } + }, + "dataSourceSpecBinding": { + "settlementDataProperty": "prices.ETH.value", + "tradingTerminationProperty": "trading.terminated.ETH5" + } + } + }, + "metadata": ["sector:energy", "sector:tech", "source:docs.vega.xyz"], + "priceMonitoringParameters": { + "triggers": [ + { + "horizon": "43200", + "probability": "0.9999999", + "auctionExtension": "600" + } + ] + }, + "liquidityMonitoringParameters": { + "targetStakeParameters": { + "timeWindow": "3600", + "scalingFactor": 10 + }, + "triggeringRatio": "0.7", + "auctionExtension": "1" + }, + "logNormal": { + "tau": 0.0001140771161, + "riskAversionParameter": 0.01, + "params": { + "mu": 0, + "r": 0.016, + "sigma": 0.5 + } + } + } + }, + "closingTimestamp": 0, + "enactmentTimestamp": 0 + } +} diff --git a/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts index dc1e18fc2..f97a5ac1b 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts @@ -7,17 +7,12 @@ import { import { createRawProposal, createTenDigitUnixTimeStampForSpecifiedDays, - enterUniqueFreeFormProposalBody, generateFreeFormProposalTitle, getDateFormatForSpecifiedDays, - getProposalIdFromList, + getProposalFromTitle, getProposalInformationFromTable, - getSubmittedProposalFromProposalList, - goToMakeNewProposal, - governanceProposalType, + submitUniqueRawProposal, 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'; @@ -38,6 +33,8 @@ const proposalDetailsTitle = '[data-testid="proposal-title"]'; const proposalDetailsDescription = '[data-testid="proposal-description"]'; const openProposals = '[data-testid="open-proposals"]'; const viewProposalButton = '[data-testid="view-proposal-btn"]'; +const voteBreakdownToggle = 'vote-breakdown-toggle'; +const proposalTermsToggle = 'proposal-terms-toggle'; describe( 'Governance flow for proposal details', @@ -62,23 +59,25 @@ describe( // 3001-VOTE-050 3001-VOTE-054 3001-VOTE-055 3002-PROP-019 it('Newly created raw proposal details - shows proposal title and full description', function () { + const proposalDescription = + 'I propose that everyone evaluate the following IPFS document and vote Yes if they agree. bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si'; + createRawProposal(); cy.get('@rawProposal').then((rawProposal) => { - getProposalIdFromList(rawProposal.rationale.title); - cy.get('@proposalIdText').then((proposalId) => { - cy.get(openProposals).within(() => { - cy.get(`#${proposalId}`).within(() => { - cy.get(viewProposalButton).should('be.visible').click(); - }); + cy.get(openProposals).within(() => { + getProposalFromTitle(rawProposal.rationale.title).within(() => { + cy.get(viewProposalButton).should('be.visible').click(); }); }); - cy.get(proposalDetailsTitle) - .should('contain', rawProposal.rationale.title) - .and('be.visible'); + cy.get(proposalDetailsTitle).should( + 'contain.text', + rawProposal.rationale.title + ); cy.get(proposalDetailsDescription) - .should('contain', rawProposal.rationale.description) - .and('be.visible'); + .find('p') + .should('have.text', proposalDescription); }); + cy.getByTestId(proposalTermsToggle).click(); // 3001-VOTE-052 cy.get('code.language-json') .should('exist') @@ -89,33 +88,36 @@ describe( // 3001-VOTE-043 it('Newly created freeform proposal details - shows proposed and closing dates', function () { - const closingVoteHrs = '72'; const proposalTitle = generateFreeFormProposalTitle(); const proposalTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(3); + // const currentDate = new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000) + // const proposedDate = new Date(currentDate.getTime() + 60000) - goToMakeNewProposal(governanceProposalType.FREEFORM); - enterUniqueFreeFormProposalBody(closingVoteHrs, proposalTitle); - waitForProposalSubmitted(); - waitForProposalSync(); + submitUniqueRawProposal({ + proposalTitle: proposalTitle, + closingTimestamp: proposalTimeStamp, + }); navigateTo(navigation.proposals); - getSubmittedProposalFromProposalList(proposalTitle).within(() => + getProposalFromTitle(proposalTitle).within(() => cy.get(viewProposalButton).click() ); cy.wrap( formatDateWithLocalTimezone(new Date(proposalTimeStamp * 1000)) ).then((closingDate) => { - getProposalInformationFromTable('Closes on') - .contains(closingDate) - .should('be.visible'); + getProposalInformationFromTable('Closes on').should( + 'have.text', + closingDate + ); }); cy.wrap( formatDateWithLocalTimezone( new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000) ) ).then((proposalDate) => { - getProposalInformationFromTable('Proposed on') - .contains(proposalDate) - .should('be.visible'); + getProposalInformationFromTable('Proposed on').should( + 'have.text', + proposalDate + ); }); }); @@ -125,13 +127,14 @@ describe( // 3001-VOTE-067 createRawProposal(); cy.get('@rawProposal').then((rawProposal) => { - getSubmittedProposalFromProposalList( - rawProposal.rationale.title - ).within(() => cy.get(viewProposalButton).click()); + getProposalFromTitle(rawProposal.rationale.title).within(() => + cy.get(viewProposalButton).click() + ); }); cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should( 'be.visible' ); + cy.getByTestId(voteBreakdownToggle).click(); getProposalInformationFromTable('Expected to pass') .contains('👎') .should('be.visible'); @@ -151,9 +154,9 @@ describe( it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () { createRawProposal(); cy.get('@rawProposal').then((rawProposal) => { - getSubmittedProposalFromProposalList( - rawProposal.rationale.title - ).within(() => cy.get(viewProposalButton).click()); + getProposalFromTitle(rawProposal.rationale.title).within(() => + cy.get(viewProposalButton).click() + ); }); // 3001-VOTE-080 cy.getByTestId('vote-buttons').contains('against').should('be.visible'); @@ -179,6 +182,7 @@ describe( cy.get(proposalVoteProgressAgainstTokens) .contains('0.00') .and('be.visible'); + cy.getByTestId(voteBreakdownToggle).click(); getProposalInformationFromTable('Tokens for proposal') .should('have.text', (1).toFixed(2)) .and('be.visible'); @@ -220,14 +224,15 @@ describe( vegaWalletSetSpecifiedApprovalAmount('1000'); createRawProposal(); cy.get('@rawProposal').then((rawProposal) => { - getSubmittedProposalFromProposalList( - rawProposal.rationale.title - ).within(() => cy.get(viewProposalButton).click()); + getProposalFromTitle(rawProposal.rationale.title).within(() => + cy.get(viewProposalButton).click() + ); }); voteForProposal('for'); // 3001-VOTE-079 cy.contains('You voted: For').should('be.visible'); cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible'); + cy.getByTestId(voteBreakdownToggle).click(); getProposalInformationFromTable('Total Supply') .invoke('text') .then((totalSupply) => { @@ -235,14 +240,15 @@ describe( (Number(totalSupply.replace(/,/g, '')) * 0.001) / 100 ).toFixed(2); + ethereumWalletConnect(); ensureSpecifiedUnstakedTokensAreAssociated( tokensRequiredToAchieveResult ); navigateTo(navigation.proposals); cy.get('@rawProposal').then((rawProposal) => { - getSubmittedProposalFromProposalList( - rawProposal.rationale.title - ).within(() => cy.get(viewProposalButton).click()); + getProposalFromTitle(rawProposal.rationale.title).within(() => + cy.get(viewProposalButton).click() + ); }); cy.get(proposalVoteProgressForPercentage) .contains('100.00%') @@ -259,6 +265,7 @@ describe( cy.get(proposalVoteProgressAgainstTokens) .contains('0.00') .and('be.visible'); + cy.getByTestId(voteBreakdownToggle).click(); getProposalInformationFromTable('Total tokens voted percentage') .should('have.text', '0.00%') .and('be.visible'); diff --git a/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts index 25533185e..022dbf90d 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts @@ -58,14 +58,12 @@ context( .parentsUntil(proposalListItem) .last() .within(() => { - cy.get(proposalStatus).should('have.text', 'Enacted '); + cy.get(proposalStatus).should('have.text', 'Enacted'); cy.get(viewProposalButton).click(); }); }); cy.getByTestId('proposal-type').should('have.text', 'New market'); - getProposalInformationFromTable('State') - .contains('Enacted') - .and('be.visible'); + cy.get(proposalStatus).should('have.text', 'Enacted'); cy.get(votesTable).within(() => { cy.contains('Vote passed.').should('be.visible'); cy.contains('Voting has ended.').should('be.visible'); @@ -87,16 +85,10 @@ context( .last() .within(() => cy.get(viewProposalButton).click()); }); - getProposalInformationFromTable('State') - .contains('Open') - .and('be.visible'); + cy.get(proposalStatus).should('have.text', 'Open'); voteForProposal('for'); - getProposalInformationFromTable('State') // 3001-VOTE-047 - .contains('Passed', proposalTimeout) - .and('be.visible'); - getProposalInformationFromTable('State') - .contains('Enacted', proposalTimeout) - .and('be.visible'); + cy.get(proposalStatus, proposalTimeout).should('have.text', 'Passed'); + cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted'); cy.get(votesTable).within(() => { cy.contains('Vote passed.').should('be.visible'); cy.contains('Voting has ended.').should('be.visible'); @@ -121,13 +113,9 @@ context( .last() .within(() => cy.get(viewProposalButton).click()); }); - getProposalInformationFromTable('State') - .contains('Open') - .and('be.visible'); + cy.get(proposalStatus).should('have.text', 'Open'); voteForProposal('for'); - getProposalInformationFromTable('State') - .contains('Enacted', proposalTimeout) - .and('be.visible'); + cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted'); }); // 3001-VOTE-048 3001-VOTE-049 3001-VOTE-050 @@ -144,12 +132,8 @@ context( .last() .within(() => cy.get(viewProposalButton).click()); }); - getProposalInformationFromTable('State') - .contains('Open') - .and('be.visible'); - getProposalInformationFromTable('State') // 3001-VOTE-047 - .contains('Declined', proposalTimeout) - .and('be.visible'); + cy.get(proposalStatus).should('have.text', 'Open'); + cy.get(proposalStatus, proposalTimeout).should('have.text', 'Declined'); getProposalInformationFromTable('Rejection reason') .contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED') .and('be.visible'); diff --git a/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts index 41014e847..9f08a4cfc 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts @@ -5,10 +5,11 @@ import { enterRawProposalBody, enterUniqueFreeFormProposalBody, generateFreeFormProposalTitle, + getProposalFromTitle, getProposalInformationFromTable, - getSubmittedProposalFromProposalList, goToMakeNewProposal, governanceProposalType, + submitUniqueRawProposal, voteForProposal, waitForProposalSubmitted, waitForProposalSync, @@ -81,7 +82,6 @@ context( }); vegaWalletSetSpecifiedApprovalAmount('1000'); - cy.associateTokensToVegaWallet('1'); }); beforeEach('visit governance tab', function () { @@ -95,7 +95,8 @@ context( navigateTo(navigation.proposals); }); - it('Should be able to see that no proposals exist', function () { + // Test can only pass if run before other proposal tests. + it.skip('Should be able to see that no proposals exist', function () { // 3001-VOTE-003 cy.get(noOpenProposals) .should('be.visible') @@ -107,7 +108,7 @@ context( // 3002-PROP-002 // 3002-PROP-003 - it('Submit a proposal form - shows how many vega tokens are required to make a proposal', function () { + it('Proposal form - shows how many vega tokens are required to make a proposal', function () { // 3002-PROP-005 goToMakeNewProposal(governanceProposalType.NEW_MARKET); cy.contains( @@ -115,8 +116,9 @@ context( ).should('be.visible'); }); + // Skipping as currently unable to propose using forms other than raw // 3002-PROP-011 - it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () { + it.skip('Able to submit a valid freeform proposal - with minimum required tokens associated', function () { goToMakeNewProposal(governanceProposalType.FREEFORM); cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008 cy.get(maxVoteButton).should('be.visible'); @@ -140,16 +142,13 @@ context( closeStakingDialog(); cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2'); - - navigateTo(navigation.proposals); - goToMakeNewProposal(governanceProposalType.FREEFORM); - enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle()); - waitForProposalSubmitted(); + createRawProposal(); }); - it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () { + it.skip('Creating a proposal - proposal rejected - when closing time sooner than system default', function () { goToMakeNewProposal(governanceProposalType.FREEFORM); enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle()); + cy.contains('Awaiting network confirmation', epochTimeout).should( 'not.exist' ); @@ -158,7 +157,7 @@ context( .should('equal', 'Value must be greater than or equal to 1.'); }); - it('Creating a proposal - proposal rejected - when closing time later than system default', function () { + it.skip('Creating a proposal - proposal rejected - when closing time later than system default', function () { goToMakeNewProposal(governanceProposalType.FREEFORM); enterUniqueFreeFormProposalBody( '100000', @@ -185,17 +184,13 @@ context( navigateTo(navigation.proposals); cy.get(rejectProposalsLink).click(); cy.get('@rawProposal').then((rawProposal) => { - getSubmittedProposalFromProposalList( - rawProposal.rationale.title - ).within(() => { + getProposalFromTitle(rawProposal.rationale.title).within(() => { cy.contains('Rejected').should('be.visible'); cy.contains('Close time too late').should('be.visible'); cy.get(viewProposalButton).click(); }); }); - getProposalInformationFromTable('State') - .contains('Rejected') - .and('be.visible'); + cy.getByTestId('proposal-status').should('have.text', 'Rejected'); getProposalInformationFromTable('Rejection reason') .contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE') .and('be.visible'); @@ -290,18 +285,19 @@ context( const proposalTitle = generateFreeFormProposalTitle(); ensureSpecifiedUnstakedTokensAreAssociated('1'); - goToMakeNewProposal(governanceProposalType.FREEFORM); - enterUniqueFreeFormProposalBody('50', proposalTitle); - waitForProposalSubmitted(); + submitUniqueRawProposal({ proposalTitle: proposalTitle }); + ethereumWalletConnect(); stakingPageDisassociateTokens('0.0001'); - cy.get(vegaWallet).within(() => { - cy.get(vegaWalletAssociatedBalance, txTimeout).should( - 'contain', - '0.9999' - ); - }); + cy.get(vegaWallet) + .first() + .within(() => { + cy.get(vegaWalletAssociatedBalance, txTimeout).should( + 'contain', + '0.9999' + ); + }); navigateTo(navigation.proposals); - getSubmittedProposalFromProposalList(proposalTitle).within(() => + getProposalFromTitle(proposalTitle).within(() => cy.get(viewProposalButton).click() ); cy.contains('Vote breakdown').should('be.visible', { @@ -319,9 +315,9 @@ context( cy.get('[data-testid="manage-vega-wallet"]:visible').click(); cy.get('[data-testid="disconnect"]').click(); cy.get('@rawProposal').then((rawProposal) => { - getSubmittedProposalFromProposalList( - rawProposal.rationale.title - ).within(() => cy.get(viewProposalButton).click()); + getProposalFromTitle(rawProposal.rationale.title).within(() => + cy.get(viewProposalButton).click() + ); }); // 3001-VOTE-075 // 3001-VOTE-076 diff --git a/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts index a7885b92a..bef728f4b 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts @@ -8,6 +8,7 @@ import { import { getProposalInformationFromTable, goToMakeNewProposal, + governanceProposalType, voteForProposal, waitForProposalSubmitted, } from '../../support/governance.functions'; @@ -56,18 +57,8 @@ const fUSDCId = const epochTimeout = Cypress.env('epochTimeout'); const proposalTimeout = { timeout: 14000 }; -const governanceProposalType = { - NETWORK_PARAMETER: 'Network parameter', - NEW_MARKET: 'New market', - UPDATE_MARKET: 'Update market', - NEW_ASSET: 'New asset', - UPDATE_ASSET: 'Update asset', - FREEFORM: 'Freeform', - RAW: 'raw proposal', -}; - // 3001-VOTE-007 -context( +context.skip( 'Governance flow - form validations for different governance proposals', { tags: '@slow' }, function () { diff --git a/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts index 970795ebe..4a47ebfdc 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts @@ -6,16 +6,15 @@ import { waitForSpinner, } from '../../support/common.functions'; import { - createFreeformProposal, createRawProposal, createTenDigitUnixTimeStampForSpecifiedDays, enterRawProposalBody, generateFreeFormProposalTitle, - getProposalIdFromList, + getProposalFromTitle, getProposalInformationFromTable, - getSubmittedProposalFromProposalList, goToMakeNewProposal, governanceProposalType, + submitUniqueRawProposal, voteForProposal, waitForProposalSubmitted, waitForProposalSync, @@ -24,10 +23,14 @@ import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/stakin import { ethereumWalletConnect } from '../../support/wallet-eth.functions'; import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions'; +const proposalListItem = 'proposals-list-item'; const openProposals = '[data-testid="open-proposals"]'; -const voteStatus = '[data-testid="vote-status"]'; +const voteStatus = 'vote-status'; +const proposalType = 'proposal-type'; +const proposalStatus = 'proposal-status'; const proposalClosingDate = '[data-testid="vote-details"]'; const viewProposalButton = '[data-testid="view-proposal-btn"]'; +const voteBreakDownToggle = 'vote-breakdown-toggle'; describe('Governance flow for proposal list', { tags: '@slow' }, function () { before('connect wallets and set approval limit', function () { @@ -60,12 +63,12 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () { navigateTo(navigation.proposals); cy.get(openProposals).within(() => { - cy.get(proposalClosingDate).first().should('contain.text', 'year'); - cy.get(proposalClosingDate).should('contain.text', 'months'); cy.get(proposalClosingDate) - .last() + .first() .invoke('text') .should('match', /days|minutes/); + cy.get(proposalClosingDate).should('contain.text', 'months'); + cy.get(proposalClosingDate).last().should('contain.text', 'year'); }); }); @@ -73,36 +76,27 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () { const proposerId = Cypress.env('vegaWalletPublicKey'); const proposalTitle = generateFreeFormProposalTitle(); - createFreeformProposal(proposalTitle); - getProposalIdFromList(proposalTitle); - cy.get('@proposalIdText').then((proposalId) => { - cy.get('[data-testid="set-proposals-filter-visible"]').click(); - cy.get('[data-testid="filter-input"]').type(proposerId); - cy.get(`#${proposalId}`).should('contain', proposalId); - }); + submitUniqueRawProposal({ proposalTitle: proposalTitle }); + cy.get('[data-testid="set-proposals-filter-visible"]').click(); + cy.get('[data-testid="filter-input"]').type(proposerId); + // cy.get(`#${proposalId}`).should('contain', proposalId); + cy.contains(proposalTitle).should('be.visible'); + cy.get('[data-testid="filter-input"]').type('123'); + cy.getByTestId(proposalListItem).should('not.exist'); }); it('Newly created proposals list - shows title and portion of summary', function () { - createRawProposal(this.minProposerBalance); // 3001-VOTE-052 - cy.get('@rawProposal').then((rawProposal) => { - getProposalIdFromList(rawProposal.rationale.title); - cy.get('@proposalIdText').then((proposalId) => { - cy.get(openProposals).within(() => { - // 3001-VOTE-008 - // 3001-VOTE-034 - cy.get(`#${proposalId}`) - // 3001-VOTE-097 - .should('contain', rawProposal.rationale.title) - .and('be.visible'); - cy.get(`#${proposalId}`) - .should( - 'contain', - rawProposal.rationale.description.substring(0, 59) - ) - .and('be.visible'); - }); - }); - }); + const proposalPath = '/proposals/new-market-raw.json'; + const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3); + submitUniqueRawProposal({ + proposalBody: proposalPath, + enactmentTimestamp: enactmentTimestamp, + }); // 3001-VOTE-052 + // 3001-VOTE-008 + // 3001-VOTE-034 + // 3001-VOTE-097 + cy.contains('New Market Proposal E2E submission'); + cy.contains('Code: TEST.24h. fBTC settled future.').should('be.visible'); }); it('Newly created proposals list - shows open proposals in an open state', function () { @@ -110,23 +104,11 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () { // 3001-VOTE-035 createRawProposal(this.minProposerBalance); cy.get('@rawProposal').then((rawProposal) => { - getSubmittedProposalFromProposalList(rawProposal.rationale.title).within( - () => { - cy.get(viewProposalButton).should('be.visible').click(); - } - ); - - cy.get('@proposalIdText').then((proposalId) => { - getProposalInformationFromTable('ID') - .contains(String(proposalId)) - .and('be.visible'); + getProposalFromTitle(rawProposal.rationale.title).within(() => { + cy.get(viewProposalButton).should('be.visible'); + cy.getByTestId(proposalType).should('have.text', 'Freeform'); + cy.getByTestId(proposalStatus).should('have.text', 'Open'); }); - getProposalInformationFromTable('State') - .contains('Open') - .and('be.visible'); - getProposalInformationFromTable('Type') - .contains('Freeform') - .and('be.visible'); }); }); @@ -134,18 +116,22 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () { it('Newly created freeform proposals list - shows proposal participation - both met and not', function () { const proposalTitle = generateFreeFormProposalTitle(); - createFreeformProposal(proposalTitle); - getSubmittedProposalFromProposalList(proposalTitle).within(() => { + submitUniqueRawProposal({ proposalTitle: proposalTitle }); + getProposalFromTitle(proposalTitle).within(() => { // 3001-VOTE-039 - cy.get(voteStatus).should('have.text', 'Participation not reached'); + cy.getByTestId(voteStatus).should( + 'have.text', + 'Participation not reached' + ); cy.get(viewProposalButton).click(); }); voteForProposal('for'); navigateTo(navigation.proposals); - getSubmittedProposalFromProposalList(proposalTitle).within(() => { - cy.get(voteStatus).should('have.text', 'Set to pass'); + getProposalFromTitle(proposalTitle).within(() => { + cy.getByTestId(voteStatus).should('have.text', 'Set to pass'); cy.get(viewProposalButton).click(); }); + cy.getByTestId(voteBreakDownToggle).click(); getProposalInformationFromTable('Token participation met') .contains('👍') .should('be.visible'); diff --git a/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts b/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts index 6d85d1ead..f3aee5c79 100644 --- a/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts @@ -96,7 +96,7 @@ context( navigateTo(navigation.validators); // 2002-SINC-007 - validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%'); + validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%'); }); it('Able to view validators staked by me', function () { @@ -146,7 +146,7 @@ context( verifyThisEpochValue(2.0); closeStakingDialog(); navigateTo(navigation.validators); - validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%'); + validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%'); }); it('Able to stake against a validator - using vega from both wallet and vesting contract', function () { @@ -166,10 +166,11 @@ context( verifyThisEpochValue(6.0); closeStakingDialog(); navigateTo(navigation.validators); - validateValidatorListTotalStakeAndShare('0', '6.00', '100.00%'); + validateValidatorListTotalStakeAndShare('0', '3,006.00', '50.05%'); }); it('Able to stake against multiple validators', function () { + vegaWalletTeardown(); stakingPageAssociateTokens('5'); verifyUnstakedBalance(5.0); cy.get('button').contains('Select a validator to nominate').click(); @@ -197,14 +198,10 @@ context( .eq(1) .within(() => { cy.getByTestId(stakeValidatorListTotalStake) - .should('have.text', '2.00') + .should('have.text', '3,002.00') .and('be.visible'); cy.getByTestId(stakeValidatorListTotalShare) - .should('have.text', '66.67%') - .and('be.visible'); - cy.getByTestId(stakeValidatorListTotalStake) - .scrollIntoView() - .should('have.text', '2.00') + .should('have.text', '50.01%') .and('be.visible'); }); cy.get(`[row-id="${1}"]`) @@ -212,14 +209,10 @@ context( .within(() => { cy.getByTestId(stakeValidatorListTotalStake) .scrollIntoView() - .should('have.text', '1.00') + .should('have.text', '3,001.00') .and('be.visible'); cy.getByTestId(stakeValidatorListTotalShare) - .should('have.text', '33.33%') - .and('be.visible'); - cy.getByTestId(stakeValidatorListTotalStake) - .scrollIntoView() - .should('have.text', '1.00') + .should('have.text', '49.99%') .and('be.visible'); }); }); @@ -282,7 +275,7 @@ context( txTimeout ); navigateTo(navigation.validators); - validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%'); + validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%'); cy.getByTestId(userStakeBtn).should('not.exist'); cy.getByTestId(userStake).should('not.exist'); @@ -354,7 +347,7 @@ context( txTimeout ); navigateTo(navigation.validators); - validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%'); + validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%'); }); it('Disassociating all vesting contract tokens max - removes all staked tokens', function () { @@ -382,7 +375,7 @@ context( txTimeout ); navigateTo(navigation.validators); - validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%'); + validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%'); }); it('Disassociating some tokens - prioritizes unstaked tokens', function () { @@ -404,7 +397,7 @@ context( }); verifyStakedBalance(2.0); navigateTo(navigation.validators); - validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%'); + validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%'); }); it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () { diff --git a/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts b/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts index f08816d12..16f91a941 100644 --- a/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts @@ -111,10 +111,10 @@ context( // 1004-ASSO-028 // 1004-ASSO-029 // 1004-ASSO-031 - + vegaWalletTeardown(); stakingPageAssociateTokens('2'); verifyEthWalletAssociatedBalance('2.0'); - verifyEthWalletTotalAssociatedBalance('2.0'); + verifyEthWalletTotalAssociatedBalance('6,002.00'); cy.get('button').contains('Select a validator to nominate').click(); stakingPageDisassociateTokens('2'); cy.getByTestId('currency-title', txTimeout).should( @@ -125,17 +125,18 @@ context( validateWalletCurrency('Pending association', '2.00'); validateWalletCurrency('Total associated after pending', '0.00'); cy.getByTestId('currency-title', txTimeout).should('have.length', 6); - cy.getByTestId('eth-wallet-associated-balances', txTimeout).should( - 'not.exist' - ); - verifyEthWalletTotalAssociatedBalance('0.00'); + cy.get( + '[data-testid="eth-wallet-associated-balances"]:visible', + txTimeout + ).should('have.length', 2); + verifyEthWalletTotalAssociatedBalance('6,000.00'); }); it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () { //1004-ASSO-011 stakingPageAssociateTokens('1001', { approve: true }); verifyEthWalletAssociatedBalance('1,001.00'); - verifyEthWalletTotalAssociatedBalance('1,001.00'); + verifyEthWalletTotalAssociatedBalance('7,001.00'); cy.get(vegaWallet) .last() .within(() => { diff --git a/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts b/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts index 74b90d2c8..1d5586c0a 100644 --- a/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts @@ -47,11 +47,8 @@ context( function () { before('visit withdrawals and connect vega wallet', function () { cy.visit('/'); - // When running tests locally, will fail if run without restarting capsule - cy.updateCapsuleMultiSig().then(() => { - ethereumWalletConnect(); - depositAsset(usdcEthAddress, '1000', 5); - }); + ethereumWalletConnect(); + depositAsset(usdcEthAddress, '1000', 5); }); beforeEach('Navigate to withdrawal page', function () { diff --git a/apps/governance-e2e/src/integration/view/pubkey-view.cy.ts b/apps/governance-e2e/src/integration/view/pubkey-view.cy.ts index e12225587..b92e59e7e 100644 --- a/apps/governance-e2e/src/integration/view/pubkey-view.cy.ts +++ b/apps/governance-e2e/src/integration/view/pubkey-view.cy.ts @@ -9,6 +9,7 @@ import { import { enterUniqueFreeFormProposalBody, goToMakeNewProposal, + governanceProposalType, } from '../../support/governance.functions'; import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions'; @@ -50,7 +51,7 @@ context('View functionality with public key', { tags: '@smoke' }, 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.`; navigateTo(navigation.proposals); - goToMakeNewProposal('Freeform'); + goToMakeNewProposal(governanceProposalType.FREEFORM); enterUniqueFreeFormProposalBody('50', 'pub key proposal test'); cy.getByTestId('dialog-content') .first() diff --git a/apps/governance-e2e/src/support/governance.functions.ts b/apps/governance-e2e/src/support/governance.functions.ts index 7b8372d07..8d35b8522 100644 --- a/apps/governance-e2e/src/support/governance.functions.ts +++ b/apps/governance-e2e/src/support/governance.functions.ts @@ -1,8 +1,12 @@ import { format } from 'date-fns'; -import { closeDialog, navigateTo, navigation } from './common.functions'; +import { + closeDialog, + navigateTo, + navigation, + waitForSpinner, +} 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"]'; @@ -46,6 +50,53 @@ export function enterRawProposalBody(timestamp: number) { }); } +export function submitUniqueRawProposal(proposalFields: { + proposalBody?: string; + proposalTitle?: string; + proposalDescription?: string; + closingTimestamp?: number; + enactmentTimestamp?: number; + submit?: boolean; +}) { + goToMakeNewProposal(governanceProposalType.RAW); + let proposalBodyPath = '/proposals/raw.json'; + if (proposalFields.proposalBody) { + proposalBodyPath = proposalFields.proposalBody; + } + cy.fixture(proposalBodyPath).then((rawProposal) => { + if (proposalFields.proposalTitle) { + rawProposal.rationale.title = proposalFields.proposalTitle; + cy.wrap(proposalFields.proposalTitle).as('proposalTitle'); + } + if (proposalFields.proposalDescription) { + rawProposal.rationale.description = proposalFields.proposalDescription; + } + if (proposalFields.closingTimestamp) { + rawProposal.terms.closingTimestamp = proposalFields.closingTimestamp; + } else { + const minTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(2); + rawProposal.terms.closingTimestamp = minTimeStamp; + } + if (proposalFields.enactmentTimestamp) { + rawProposal.terms.enactmentTimestamp = proposalFields.enactmentTimestamp; + } + + const proposalPayload = JSON.stringify(rawProposal); + cy.get(rawProposalData).type(proposalPayload, { + parseSpecialCharSequences: false, + delay: 2, + }); + + if (proposalFields.submit !== false) { + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.wrap(rawProposal).as('rawProposal'); + waitForProposalSubmitted(); + waitForProposalSync(); + navigateTo(navigation.proposals); + } + }); +} + export function enterUniqueFreeFormProposalBody( timestamp: string, proposalTitle: string @@ -58,6 +109,10 @@ export function enterUniqueFreeFormProposalBody( cy.getByTestId('proposal-submit').should('be.visible').click(); } +export function getProposalFromTitle(proposalTitle: string) { + return cy.contains(proposalTitle).parentsUntil(proposalListItem).last(); +} + export function getSubmittedProposalFromProposalList(proposalTitle: string) { getProposalIdFromList(proposalTitle); cy.get('@proposalIdText').then((proposalId) => { @@ -120,13 +175,17 @@ export function waitForProposalSync() { }); } -export function goToMakeNewProposal(proposalType: string) { - navigateTo(navigation.proposals); - cy.get(newProposalButton).should('be.visible').click(); +export function goToMakeNewProposal(proposalType: governanceProposalType) { + cy.visit('/proposals/propose'); + waitForSpinner(); cy.url().should('include', '/proposals/propose'); cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist'); - cy.get('li').should('contain.text', proposalType).and('be.visible'); - cy.get('li').contains(proposalType).click(); + if (proposalType == governanceProposalType.RAW) { + cy.get('[href="/proposals/propose/raw"]').click(); + } else { + cy.get('li').should('contain.text', proposalType).and('be.visible'); + cy.get('li').contains(proposalType).click(); + } } export function waitForProposalSubmitted() { @@ -163,11 +222,12 @@ export function createFreeformProposal(proposalTitle: string) { 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', -}; +export enum governanceProposalType { + NETWORK_PARAMETER = 'Network parameter', + NEW_MARKET = 'New market', + UPDATE_MARKET = 'Update market', + NEW_ASSET = 'New asset', + UPDATE_ASSET = 'Update asset', + FREEFORM = 'Freeform', + RAW = 'raw proposal', +} diff --git a/apps/governance-e2e/src/support/proposal.functions.ts b/apps/governance-e2e/src/support/proposal.functions.ts index 00bd0ece4..2ba270cd9 100644 --- a/apps/governance-e2e/src/support/proposal.functions.ts +++ b/apps/governance-e2e/src/support/proposal.functions.ts @@ -85,6 +85,132 @@ export function createFreeFormProposalTxBody(): ProposalSubmissionBody { }; } +export function createNewMarketProposalTxBody(): ProposalSubmissionBody { + const MIN_CLOSE_SEC = 5; + const MIN_ENACT_SEC = 7; + + const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC); + const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC); + const closingTimestamp = millisecondsToSeconds(closingDate.getTime()); + const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime()); + return { + proposalSubmission: { + rationale: { + title: 'New Market Proposal E2E submission', + description: 'E2E new market proposal', + }, + terms: { + newMarket: { + changes: { + decimalPlaces: '5', + positionDecimalPlaces: '5', + linearSlippageFactor: '0.001', + quadraticSlippageFactor: '0', + lpPriceRange: '10', + instrument: { + name: 'Token test market', + code: 'TEST.24h', + future: { + settlementAsset: + '73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0', + quoteName: 'fBTC', + dataSourceSpecForSettlementData: { + external: { + oracle: { + signers: [ + { + pubKey: { + key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680', + }, + }, + ], + filters: [ + { + key: { + name: 'prices.ETH.value', + type: 'TYPE_INTEGER' as const, + numberDecimalPlaces: '0', + }, + conditions: [ + { + operator: 'OPERATOR_GREATER_THAN' as const, + value: '0', + }, + ], + }, + ], + }, + }, + }, + dataSourceSpecForTradingTermination: { + external: { + oracle: { + signers: [ + { + pubKey: { + key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680', + }, + }, + ], + filters: [ + { + key: { + name: 'trading.terminated.ETH5', + type: 'TYPE_BOOLEAN' as const, + }, + conditions: [ + { + operator: 'OPERATOR_EQUALS' as const, + value: 'true', + }, + ], + }, + ], + }, + }, + }, + dataSourceSpecBinding: { + settlementDataProperty: 'prices.ETH.value', + tradingTerminationProperty: 'trading.terminated.ETH5', + }, + }, + }, + metadata: ['sector:energy', 'sector:tech', 'source:docs.vega.xyz'], + priceMonitoringParameters: { + triggers: [ + { + horizon: '43200', + probability: '0.9999999', + auctionExtension: '600', + }, + ], + }, + liquidityMonitoringParameters: { + targetStakeParameters: { + timeWindow: '3600', + scalingFactor: 10, + }, + triggeringRatio: '0.7', + auctionExtension: '1', + }, + logNormal: { + tau: 0.0001140771161, + riskAversionParameter: 0.01, + params: { + mu: 0, + r: 0.016, + sigma: 0.5, + }, + }, + }, + }, + closingTimestamp, + enactmentTimestamp, + }, + }, + }; +} + export function mockNetworkUpgradeProposal() { cy.mockGQL((req) => { aliasGQLQuery(req, 'Nodes', nodeData); diff --git a/apps/governance-e2e/src/support/wallet-teardown.functions.ts b/apps/governance-e2e/src/support/wallet-teardown.functions.ts index 7cdb12583..13883849a 100644 --- a/apps/governance-e2e/src/support/wallet-teardown.functions.ts +++ b/apps/governance-e2e/src/support/wallet-teardown.functions.ts @@ -67,7 +67,6 @@ export async function faucetAsset(assetEthAddress: string) { export async function vegaWalletTeardown() { cy.get(associatedAmountInWallet) - .should('be.visible') .invoke('text') .then((associatedAmount) => { cy.get('body').then(($body) => { @@ -82,9 +81,11 @@ export async function vegaWalletTeardown() { cy.get(vegaWalletContainer).within(() => { cy.get(associatedAmountInWallet, { timeout: transactionTimeout, - }).contains('0.00', { - timeout: transactionTimeout, - }); + }) + .should('have.length', 1, { timeout: transactionTimeout }) + .contains('0.00', { + timeout: transactionTimeout, + }); }); }); }