diff --git a/.github/workflows/e2e_tests.yml b/.github/workflows/e2e_tests.yml index bbb7f57..f89e158 100644 --- a/.github/workflows/e2e_tests.yml +++ b/.github/workflows/e2e_tests.yml @@ -24,14 +24,6 @@ on: - emerynet - devnet - xnet - gov1_mnemonic: - description: 'Mnemonic for gov1 wallet' - required: false - type: string - gov2_mnemonic: - description: 'Mnemonic for gov2 wallet' - required: false - type: string a3p_image_tag: description: 'Docker image tag for the a3p chain to use in testing' required: false @@ -92,8 +84,10 @@ jobs: ANVIL_FORK_URL: ${{ secrets.ANVIL_FORK_URL }} GH_PAT: ${{ secrets.GH_PAT }} GH_USERNAME: ${{ secrets.GH_USERNAME }} - GOV1_PHRASE: ${{ inputs.gov1_mnemonic || secrets.GOV1_PHRASE }} - GOV2_PHRASE: ${{ inputs.gov2_mnemonic || secrets.GOV2_PHRASE }} + GOV1_PHRASE: ${{ secrets.GOV1_PHRASE }} + GOV2_PHRASE: ${{ secrets.GOV2_PHRASE }} + GOV3_PHRASE: ${{ secrets.GOV3_PHRASE }} + GOV4_PHRASE: ${{ secrets.GOV4_PHRASE }} # cypress dashboard GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CYPRESS_PROJECT_ID: ${{ secrets.CYPRESS_PROJECT_ID }} diff --git a/tests/e2e/docker-compose.yml b/tests/e2e/docker-compose.yml index e65e018..ec261a6 100644 --- a/tests/e2e/docker-compose.yml +++ b/tests/e2e/docker-compose.yml @@ -39,7 +39,8 @@ services: - CYPRESS_AGORIC_NET=${CYPRESS_AGORIC_NET} - CYPRESS_GOV1_PHRASE=${GOV1_PHRASE} - CYPRESS_GOV2_PHRASE=${GOV2_PHRASE} - - SECRET_WORDS="orbit bench unit task food shock brand bracket domain regular warfare company announce wheel grape trust sphere boy doctor half guard ritual three ecology" + - CYPRESS_GOV3_PHRASE=${GOV3_PHRASE} + - CYPRESS_GOV4_PHRASE=${GOV4_PHRASE} depends_on: - display - video diff --git a/tests/e2e/specs/proposal.spec.js b/tests/e2e/specs/proposal.spec.js index 8a5a2d4..cd3548d 100644 --- a/tests/e2e/specs/proposal.spec.js +++ b/tests/e2e/specs/proposal.spec.js @@ -3,11 +3,14 @@ import { phrasesList, getTimeUntilVoteClose, DEFAULT_TIMEOUT } from '../utils'; describe('Make Proposal Tests', () => { let startTime; - const networkPhrases = phrasesList[Cypress.env('AGORIC_NET') || 'local']; + const AGORIC_NET = Cypress.env('AGORIC_NET') || 'local'; + const networkPhrases = phrasesList[AGORIC_NET]; const txRetryCount = 2; context('PSM tests', () => { - it('should setup two econ committee member wallets', () => { + it('should setup 4 econ committee member wallets', () => { + cy.task('info', `${AGORIC_NET}`); + cy.setupWallet({ secretWords: networkPhrases.gov1Phrase, walletName: 'gov1', @@ -16,6 +19,14 @@ describe('Make Proposal Tests', () => { secretWords: networkPhrases.gov2Phrase, walletName: 'gov2', }); + cy.setupWallet({ + secretWords: networkPhrases.gov3Phrase, + walletName: 'gov3', + }); + cy.setupWallet({ + secretWords: networkPhrases.gov4Phrase, + walletName: 'gov4', + }); }); it('should connect to wallet', () => { @@ -54,7 +65,10 @@ describe('Make Proposal Tests', () => { cy.acceptAccess(); }); - it('should allow gov1 to create a proposal', () => { + it('should allow gov2 to create a proposal', () => { + cy.switchWallet('gov2'); + cy.reload(); + // open PSM and select token cy.get('button').contains('PSM').click(); cy.get('button').contains('AUSD').click(); @@ -78,7 +92,7 @@ describe('Make Proposal Tests', () => { }); it( - 'should confirm transaction for gov1 to create a proposal', + 'should confirm transaction for gov2 to create a proposal', { retries: { runMode: txRetryCount, @@ -290,4 +304,213 @@ describe('Make Proposal Tests', () => { }); }); }); + + context('Gov4 tests', () => { + it('should allow gov4 to create a proposal', () => { + cy.switchWallet('gov4'); + cy.reload(); + + // open Values and select manager 0 + cy.get('button').contains('Vaults').click(); + cy.get('button').contains('Select Manager').click(); + cy.get('button').contains('manager0').click(); + + // Change debt limit and proposal time to 1 min + cy.get('label') + .contains('DebtLimit') + .parent() + .within(() => { + cy.get('input').spread(element => { + cy.get('input').clear().type(element.value); + }); + }); + cy.get('label') + .contains('Minutes until close of vote') + .parent() + .within(() => { + cy.get('input').clear().type(networkPhrases.minutes); + }); + }); + + it( + 'should confirm transaction for gov4 to create a proposal', + { + retries: { + runMode: txRetryCount, + }, + }, + () => { + cy.get('[value="Propose Parameter Change"]').click(); + + // Submit proposal and wait for confirmation + cy.confirmTransaction(); + cy.get('p') + .contains('sent', { timeout: DEFAULT_TIMEOUT }) + .should('be.visible') + .then(() => { + startTime = Date.now(); + }); + }, + ); + + it('should allow gov4 to vote on the proposal', () => { + cy.visit(`/?agoricNet=${networkPhrases.network}`); + + // Open vote, click on yes and submit + cy.get('button').contains('Vote').click(); + cy.get('p').contains('YES').click(); + }); + + it( + 'should confirm transaction for gov4 to vote on the proposal', + { + retries: { + runMode: txRetryCount, + }, + }, + () => { + cy.get('input:enabled[value="Submit Vote"]').click(); + + // Wait for vote to confirm + cy.confirmTransaction(); + cy.get('p') + .contains('sent', { timeout: DEFAULT_TIMEOUT }) + .should('be.visible'); + }, + ); + + it('should allow gov2 to vote on the proposal', () => { + cy.switchWallet('gov2'); + cy.visit(`/?agoricNet=${networkPhrases.network}`); + + // Open vote, click on yes and submit + cy.get('button').contains('Vote').click(); + cy.get('p').contains('YES').click(); + }); + + it( + 'should confirm transaction for gov2 to vote on the proposal', + { + retries: { + runMode: txRetryCount, + }, + }, + () => { + cy.get('input:enabled[value="Submit Vote"]').click(); + + // Wait for vote to confirm + cy.confirmTransaction(); + cy.get('p') + .contains('sent', { timeout: DEFAULT_TIMEOUT }) + .should('be.visible'); + }, + ); + + it('should wait for proposal to pass', () => { + // Wait for 1 minute to pass + cy.wait(getTimeUntilVoteClose(startTime, networkPhrases.minutes)); + cy.visit(`/?agoricNet=${networkPhrases.network}`); + + cy.get('button').contains('History').click(); + + // Select the first element proposal containing ATOM and check + // its status should be accepted + cy.get('code') + .contains('VaultFactory - ATOM') + .parent() + .parent() + .parent() + .within(() => { + cy.get('span').contains('Change Accepted').should('be.visible'); + }); + }); + }); + + context('Gov3 tests', () => { + it('should not allow gov3 to create a proposal', () => { + cy.switchWallet('gov3'); + cy.reload(); + cy.contains('button', 'PSM').click(); + cy.get('button').contains('AUSD').click(); + cy.get('button').contains(networkPhrases.token).click(); + + // Change mint limit and proposal time to 1 min + cy.get('label') + .contains('Set Mint Limit') + .parent() + .within(() => { + cy.get('input').spread(_ => { + cy.get('input').clear().type(900); + }); + }); + cy.get('label') + .contains('Minutes until close of vote') + .parent() + .within(() => { + cy.get('input').clear().type(networkPhrases.minutes); + }); + + cy.get('[value="Propose Parameter Change"]').should('be.disabled'); + }); + + it('should allow gov1 to create a proposal', () => { + cy.switchWallet('gov1'); + cy.reload(); + + // open Values and select manager 0 + cy.get('button').contains('Vaults').click(); + cy.get('button').contains('Select Manager').click(); + cy.get('button').contains('manager0').click(); + + // Change debt limit and proposal time to 1 min + cy.get('label') + .contains('DebtLimit') + .parent() + .within(() => { + cy.get('input').spread(element => { + cy.get('input').clear().type(element.value); + }); + }); + cy.get('label') + .contains('Minutes until close of vote') + .parent() + .within(() => { + cy.get('input').clear().type(networkPhrases.minutes); + }); + }); + + it( + 'should confirm transaction for gov1 to create a proposal', + { + retries: { + runMode: txRetryCount, + }, + }, + () => { + cy.get('[value="Propose Parameter Change"]').click(); + + // Submit proposal and wait for confirmation + cy.confirmTransaction(); + cy.get('p') + .contains('sent', { timeout: DEFAULT_TIMEOUT }) + .should('be.visible') + .then(() => { + startTime = Date.now(); + }); + }, + ); + + it('should not allow gov3 to vote on the proposal', () => { + cy.switchWallet('gov3'); + cy.reload(); + cy.get('button').contains('Vote').click(); + + // UNTIL https://github.com/Agoric/dapp-econ-gov/issues/144 + cy.get('p') + .contains( + 'You must first have received an invitation to the Economic Committee.', + ) + .should('be.visible'); + }); + }); }); diff --git a/tests/e2e/support.js b/tests/e2e/support.js index 73d2d1f..171e77a 100644 --- a/tests/e2e/support.js +++ b/tests/e2e/support.js @@ -1 +1,7 @@ import '@agoric/synpress/support/index'; + +Cypress.Commands.add('skipWhen', function (expression) { + if (expression) { + this.skip(); + } +}); diff --git a/tests/e2e/utils.js b/tests/e2e/utils.js index 7737e3d..422977d 100644 --- a/tests/e2e/utils.js +++ b/tests/e2e/utils.js @@ -9,6 +9,9 @@ export const phrasesList = { networkConfigURL: 'https://emerynet.agoric.net/network-config', gov1Phrase: Cypress.env('GOV1_PHRASE'), gov2Phrase: Cypress.env('GOV2_PHRASE'), + // UNTIL https://github.com/Agoric/dapp-econ-gov/issues/144 + gov3Phrase: Cypress.env('GOV4_PHRASE'), + gov4Phrase: Cypress.env('GOV3_PHRASE'), }, devnet: { isLocal: false, @@ -18,6 +21,9 @@ export const phrasesList = { networkConfigURL: 'https://devnet.agoric.net/network-config', gov1Phrase: Cypress.env('GOV1_PHRASE'), gov2Phrase: Cypress.env('GOV2_PHRASE'), + // UNTIL https://github.com/Agoric/dapp-econ-gov/issues/144 + gov3Phrase: Cypress.env('GOV4_PHRASE'), + gov4Phrase: Cypress.env('GOV3_PHRASE'), }, xnet: { isLocal: false, @@ -27,6 +33,9 @@ export const phrasesList = { networkConfigURL: 'https://xnet.agoric.net/network-config', gov1Phrase: Cypress.env('GOV1_PHRASE'), gov2Phrase: Cypress.env('GOV2_PHRASE'), + // UNTIL https://github.com/Agoric/dapp-econ-gov/issues/144 + gov3Phrase: Cypress.env('GOV4_PHRASE'), + gov4Phrase: Cypress.env('GOV3_PHRASE'), }, local: { isLocal: true, @@ -37,6 +46,11 @@ export const phrasesList = { 'such field health riot cost kitten silly tube flash wrap festival portion imitate this make question host bitter puppy wait area glide soldier knee', gov2Phrase: 'physical immune cargo feel crawl style fox require inhale law local glory cheese bring swear royal spy buyer diesel field when task spin alley', + // UNTIL https://github.com/Agoric/dapp-econ-gov/issues/144 + gov3Phrase: + 'spike siege world rather ordinary upper napkin voice brush oppose junior route trim crush expire angry seminar anchor panther piano image pepper chest alone', + gov4Phrase: + 'tackle hen gap lady bike explain erode midnight marriage wide upset culture model select dial trial swim wood step scan intact what card symptom', }, };