From acfa2f4d2c2b7ce865a9b26a818fe5714e386517 Mon Sep 17 00:00:00 2001 From: apanizo Date: Fri, 1 Jun 2018 13:54:27 +0200 Subject: [PATCH 1/4] WA-238 Created DOM test for multisig tx on safe with 3 owners with 3 as threshold --- .../safe/component/Safe.multisig.txs.test.js | 190 ++++++++++++++++++ .../test/builder/deployedSafe.builder.js | 36 +++- 2 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 src/routes/safe/component/Safe.multisig.txs.test.js diff --git a/src/routes/safe/component/Safe.multisig.txs.test.js b/src/routes/safe/component/Safe.multisig.txs.test.js new file mode 100644 index 0000000000..8784e2fee6 --- /dev/null +++ b/src/routes/safe/component/Safe.multisig.txs.test.js @@ -0,0 +1,190 @@ +// @flow +import * as React from 'react' +import TestUtils from 'react-dom/test-utils' +import { Provider } from 'react-redux' +import { ConnectedRouter } from 'react-router-redux' +import Button from '~/components/layout/Button' +import { aNewStore, history } from '~/store' +import { addEtherTo } from '~/test/addEtherTo' +import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder' +import { SAFELIST_ADDRESS } from '~/routes/routes' +import SafeView from '~/routes/safe/component/Safe' +import AppRoutes from '~/routes' +import { getBalanceInEtherOf, getWeb3 } from '~/wallets/getWeb3' +import { sleep } from '~/utils/timer' +import { ADD_MULTISIG_BUTTON_TEXT, SEE_MULTISIG_BUTTON_TEXT } from '~/routes/safe/component/Safe/MultisigTx' +import AddTransactionComponent from '~/routes/safe/component/AddTransaction' +import TransactionsComponent from '~/routes/safe/component/Transactions' +import TransactionComponent from '~/routes/safe/component/Transactions/Transaction' +import { promisify } from '~/utils/promisify' +import { processTransaction } from '~/routes/safe/component/Transactions/processTransactions' +import { safeTransactionsSelector, confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index' +import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' + +const renderSafe = localStore => ( + TestUtils.renderIntoDocument(( + + + + + + )) +) + +describe('React DOM TESTS > Multisig transactions from safe [3 owners & 3 threshold] ', () => { + let SafeDom + let store + let address + let accounts + beforeEach(async () => { + // create store + store = aNewStore() + // deploy safe updating store + address = await aDeployedSafe(store, 10, 3, 3) + // navigate to SAFE route + history.push(`${SAFELIST_ADDRESS}/${address}`) + SafeDom = renderSafe(store) + accounts = await promisify(cb => getWeb3().eth.getAccounts(cb)) + }) + + const listTxs = () => { + const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView) + + // $FlowFixMe + const buttons = TestUtils.scryRenderedComponentsWithType(Safe, Button) + const seeTx = buttons[2] + expect(seeTx.props.children).toEqual(SEE_MULTISIG_BUTTON_TEXT) + TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(seeTx, 'button')[0]) + } + + const createMultisigTxFilling = async () => { + // Get AddTransaction form component + const AddTransaction = TestUtils.findRenderedComponentWithType(SafeDom, AddTransactionComponent) + + // $FlowFixMe + const inputs = TestUtils.scryRenderedDOMComponentsWithTag(AddTransaction, 'input') + const name = inputs[0] + const destination = inputs[1] + const amountInEth = inputs[2] + TestUtils.Simulate.change(name, { target: { value: 'Buying betteries' } }) + TestUtils.Simulate.change(amountInEth, { target: { value: '0.01' } }) + TestUtils.Simulate.change(destination, { target: { value: store.getState().providers.account } }) + + // $FlowFixMe + const form = TestUtils.findRenderedDOMComponentWithTag(AddTransaction, 'form') + + TestUtils.Simulate.submit(form) // fill the form + TestUtils.Simulate.submit(form) // confirming data + return sleep(4000) + } + + const checkBalanceOf = async (addressToTest: string, value: string) => { + const safeBalance = await getBalanceInEtherOf(addressToTest) + expect(safeBalance).toBe(value) + } + + const addFundsTo = async (destination: string) => { + // add funds to safe + await addEtherTo(destination, '0.1') + const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView) + + // $FlowFixMe + const buttons = TestUtils.scryRenderedComponentsWithType(Safe, Button) + const addTxButton = buttons[1] + expect(addTxButton.props.children).toEqual(ADD_MULTISIG_BUTTON_TEXT) + await sleep(1800) // Give time to enable Add button + TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(addTxButton, 'button')[0]) + } + + const getTransactionFromReduxStore = () => { + const transactions = safeTransactionsSelector(store.getState(), { safeAddress: address }) + + return transactions.get(0) + } + + const getAlreadyConfirmed = () => { + const tx = getTransactionFromReduxStore() + const confirmed = confirmationsTransactionSelector(store.getState(), { transaction: tx }) + + return confirmed + } + + const getTagFromTransaction = (tag: string) => { + const Transactions = TestUtils.findRenderedComponentWithType(SafeDom, TransactionsComponent) + if (!Transactions) throw new Error() + const Transaction = TestUtils.findRenderedComponentWithType(Transactions, TransactionComponent) + if (!Transaction) throw new Error() + + return TestUtils.scryRenderedDOMComponentsWithTag(Transaction, tag) + } + + const expandTransactionOf = async (numOwners) => { + const paragraphs = getTagFromTransaction('p') + TestUtils.Simulate.click(paragraphs[2]) // expanded + await sleep(1000) // Time to expand + const paragraphsExpanded = getTagFromTransaction('p') + const threshold = paragraphsExpanded[5] + expect(threshold.innerHTML).toContain('confirmations needed') + TestUtils.Simulate.click(threshold) // expanded + await sleep(1000) // Time to expand + expect(paragraphsExpanded.length).toBe(paragraphs.length + numOwners) + } + + const confirmOwners = async (...statusses: string[]) => { + const paragraphsWithOwners = getTagFromTransaction('h3') + for (let i = 0; i < statusses.length; i += 1) { + const ownerIndex = i + 6 + const ownerParagraph = paragraphsWithOwners[ownerIndex].innerHTML + expect(statusses[i]).toEqual(ownerParagraph) + } + } + + const makeConfirmation = async (executor) => { + const alreadyConfirmed = getAlreadyConfirmed() + const tx = getTransactionFromReduxStore() + await processTransaction(address, tx, alreadyConfirmed, executor) + await sleep(800) + store.dispatch(fetchTransactions()) + sleep(1800) + SafeDom = renderSafe(store) + sleep(1800) + await listTxs() + sleep(800) + await expandTransactionOf(3) + sleep(800) + } + + it('should execute transaction after 2 owners have confirmed and the last one executed correctly', async () => { + await addFundsTo(address) + await createMultisigTxFilling() + + await checkBalanceOf(address, '0.1') + await listTxs() + + const paragraphs = getTagFromTransaction('p') + + const status = paragraphs[2].innerHTML + expect(status).toBe('1 of the 3 confirmations needed') + + const confirmed = paragraphs[3].innerHTML + expect(confirmed).toBe('Waiting for the rest of confirmations') + + await expandTransactionOf(3) + await confirmOwners('Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Not confirmed]', 'Adolfo 3 Eth Account [Not confirmed]') + + await makeConfirmation(accounts[1]) + await confirmOwners('Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Not confirmed]') + + await makeConfirmation(accounts[2]) + await confirmOwners('Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Confirmed]') + + const paragraphsExecuted = getTagFromTransaction('p') + + const statusExecuted = paragraphsExecuted[2].innerHTML + expect(statusExecuted).toBe('Already executed') + + const confirmedExecuted = paragraphsExecuted[3].innerHTML + const tx = getTransactionFromReduxStore() + expect(confirmedExecuted).toBe(tx.get('tx')) + }) +}) diff --git a/src/routes/safe/store/test/builder/deployedSafe.builder.js b/src/routes/safe/store/test/builder/deployedSafe.builder.js index 0e86b59330..c5e58f96b6 100644 --- a/src/routes/safe/store/test/builder/deployedSafe.builder.js +++ b/src/routes/safe/store/test/builder/deployedSafe.builder.js @@ -8,10 +8,11 @@ import { DEPLOYED_COMPONENT_ID } from '~/routes/open/components/FormConfirmation import Open from '~/routes/open/container/Open' import { history, type GlobalState } from '~/store' import { sleep } from '~/utils/timer' -import { getProviderInfo } from '~/wallets/getWeb3' +import { getProviderInfo, getWeb3 } from '~/wallets/getWeb3' import addProvider from '~/wallets/store/actions/addProvider' import { makeProvider } from '~/wallets/store/model/provider' import withdrawn, { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdrawn/withdrawn' +import { promisify } from '~/utils/promisify' export const renderSafe = async (localStore: Store) => { const provider = await getProviderInfo() @@ -29,20 +30,34 @@ export const renderSafe = async (localStore: Store) => { ) } -const deploySafe = async (safe: React$Component<{}>, dailyLimit: string) => { +const deploySafe = async (safe: React$Component<{}>, dailyLimit: string, threshold: number, numOwners: number) => { + expect(threshold).toBeLessThanOrEqual(numOwners) const inputs = TestUtils.scryRenderedDOMComponentsWithTag(safe, 'input') const fieldName = inputs[0] const fieldOwners = inputs[1] const fieldConfirmations = inputs[2] const fieldDailyLimit = inputs[3] - TestUtils.Simulate.change(fieldOwners, { target: { value: '1' } }) + const web3 = getWeb3() + const accounts = await promisify(cb => web3.eth.getAccounts(cb)) + TestUtils.Simulate.change(fieldOwners, { target: { value: `${numOwners}` } }) + await sleep(800) const inputsExpanded = TestUtils.scryRenderedDOMComponentsWithTag(safe, 'input') - const ownerName = inputsExpanded[2] + expect(inputsExpanded.length).toBe((numOwners * 2) + 4) // 2 per owner + name, dailyLimit, confirmations, numOwners + + for (let i = 0; i < numOwners; i += 1) { + const nameIndex = (i * 2) + 2 + const addressIndex = (i * 2) + 3 + const ownerName = inputsExpanded[nameIndex] + const account = inputsExpanded[addressIndex] + + TestUtils.Simulate.change(ownerName, { target: { value: `Adolfo ${i + 1} Eth Account` } }) + TestUtils.Simulate.change(account, { target: { value: accounts[i] } }) + } TestUtils.Simulate.change(fieldName, { target: { value: 'Adolfo Safe' } }) - TestUtils.Simulate.change(fieldConfirmations, { target: { value: '1' } }) - TestUtils.Simulate.change(ownerName, { target: { value: 'Adolfo Eth Account' } }) + TestUtils.Simulate.change(fieldConfirmations, { target: { value: `${threshold}` } }) + TestUtils.Simulate.change(fieldDailyLimit, { target: { value: dailyLimit } }) const form = TestUtils.findRenderedDOMComponentWithTag(safe, 'form') @@ -67,9 +82,14 @@ const deploySafe = async (safe: React$Component<{}>, dailyLimit: string) => { return transactionHash } -export const aDeployedSafe = async (specificStore: Store, dailyLimit?: number = 0.5) => { +export const aDeployedSafe = async ( + specificStore: Store, + dailyLimit?: number = 0.5, + threshold?: number = 1, + numOwners?: number = 1, +) => { const safe: React$Component<{}> = await renderSafe(specificStore) - const deployedSafe = await deploySafe(safe, `${dailyLimit}`) + const deployedSafe = await deploySafe(safe, `${dailyLimit}`, threshold, numOwners) return deployedSafe.logs[1].args.proxy } From 9c21fb88b43e1ba5c707ac118a9d7655ae68f0d3 Mon Sep 17 00:00:00 2001 From: apanizo Date: Mon, 4 Jun 2018 09:48:32 +0200 Subject: [PATCH 2/4] WA-238 Adding tests helper for checking multisig tx with safes with 1+ owners --- src/routes/safe/test/testMultisig.js | 80 ++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/routes/safe/test/testMultisig.js diff --git a/src/routes/safe/test/testMultisig.js b/src/routes/safe/test/testMultisig.js new file mode 100644 index 0000000000..0278af92c6 --- /dev/null +++ b/src/routes/safe/test/testMultisig.js @@ -0,0 +1,80 @@ +// @flow +import TestUtils from 'react-dom/test-utils' +import { sleep } from '~/utils/timer' +import { getBalanceInEtherOf } from '~/wallets/getWeb3' +import Button from '~/components/layout/Button' +import { ADD_MULTISIG_BUTTON_TEXT, SEE_MULTISIG_BUTTON_TEXT } from '~/routes/safe/component/Safe/MultisigTx' +import { addEtherTo } from '~/test/addEtherTo' +import SafeView from '~/routes/safe/component/Safe' +import TransactionsComponent from '~/routes/safe/component/Transactions' +import TransactionComponent from '~/routes/safe/component/Transactions/Transaction' + +export const createMultisigTxFilling = async (SafeDom, AddTransactionComponent, store) => { + // Get AddTransaction form component + const AddTransaction = TestUtils.findRenderedComponentWithType(SafeDom, AddTransactionComponent) + + // $FlowFixMe + const inputs = TestUtils.scryRenderedDOMComponentsWithTag(AddTransaction, 'input') + const name = inputs[0] + const destination = inputs[1] + const amountInEth = inputs[2] + TestUtils.Simulate.change(name, { target: { value: 'Buying betteries' } }) + TestUtils.Simulate.change(amountInEth, { target: { value: '0.01' } }) + TestUtils.Simulate.change(destination, { target: { value: store.getState().providers.account } }) + + // $FlowFixMe + const form = TestUtils.findRenderedDOMComponentWithTag(AddTransaction, 'form') + + TestUtils.Simulate.submit(form) // fill the form + TestUtils.Simulate.submit(form) // confirming data + return sleep(4000) +} + +export const checkBalanceOf = async (addressToTest: string, value: string) => { + const safeBalance = await getBalanceInEtherOf(addressToTest) + expect(safeBalance).toBe(value) +} + +export const addFundsTo = async (SafeDom, destination: string) => { + // add funds to safe + await addEtherTo(destination, '0.1') + const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView) + + // $FlowFixMe + const buttons = TestUtils.scryRenderedComponentsWithType(Safe, Button) + const addTxButton = buttons[1] + expect(addTxButton.props.children).toEqual(ADD_MULTISIG_BUTTON_TEXT) + await sleep(1800) // Give time to enable Add button + TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(addTxButton, 'button')[0]) +} + +export const listTxsOf = (SafeDom) => { + const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView) + + // $FlowFixMe + const buttons = TestUtils.scryRenderedComponentsWithType(Safe, Button) + const seeTx = buttons[2] + expect(seeTx.props.children).toEqual(SEE_MULTISIG_BUTTON_TEXT) + TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(seeTx, 'button')[0]) +} + +export const getTagFromTransaction = (SafeDom, tag: string) => { + const Transactions = TestUtils.findRenderedComponentWithType(SafeDom, TransactionsComponent) + if (!Transactions) throw new Error() + const Transaction = TestUtils.findRenderedComponentWithType(Transactions, TransactionComponent) + if (!Transaction) throw new Error() + + return TestUtils.scryRenderedDOMComponentsWithTag(Transaction, tag) +} + +export const expandTransactionOf = async (SafeDom, numOwners) => { + const paragraphs = getTagFromTransaction(SafeDom, 'p') + TestUtils.Simulate.click(paragraphs[2]) // expanded + await sleep(1000) // Time to expand + const paragraphsExpanded = getTagFromTransaction(SafeDom, 'p') + const threshold = paragraphsExpanded[5] + expect(threshold.innerHTML).toContain(`confirmation${numOwners === 1 ? 's' : ''} needed`) + TestUtils.Simulate.click(threshold) // expanded + await sleep(1000) // Time to expand + expect(paragraphsExpanded.length).toBe(paragraphs.length + numOwners) +} From d31dc60645a1d4e4a5a087e07933534604bd99ff Mon Sep 17 00:00:00 2001 From: apanizo Date: Mon, 4 Jun 2018 09:49:28 +0200 Subject: [PATCH 3/4] WA-238 Adding DOM test for 1 safe with 3 owners and 1 threshold --- .../Safe.multisig.1owners1threshold.test.js} | 0 .../Safe.multisig.3owners1threshold.test.js | 75 +++++++++++++++++++ .../Safe.multisig.3owners3threshold.test.js} | 0 .../Safe.withdrawn.test.js | 0 4 files changed, 75 insertions(+) rename src/routes/safe/{component/Safe.txs.test.js => test/Safe.multisig.1owners1threshold.test.js} (100%) create mode 100644 src/routes/safe/test/Safe.multisig.3owners1threshold.test.js rename src/routes/safe/{component/Safe.multisig.txs.test.js => test/Safe.multisig.3owners3threshold.test.js} (100%) rename src/routes/safe/{component => test}/Safe.withdrawn.test.js (100%) diff --git a/src/routes/safe/component/Safe.txs.test.js b/src/routes/safe/test/Safe.multisig.1owners1threshold.test.js similarity index 100% rename from src/routes/safe/component/Safe.txs.test.js rename to src/routes/safe/test/Safe.multisig.1owners1threshold.test.js diff --git a/src/routes/safe/test/Safe.multisig.3owners1threshold.test.js b/src/routes/safe/test/Safe.multisig.3owners1threshold.test.js new file mode 100644 index 0000000000..d8cad9284f --- /dev/null +++ b/src/routes/safe/test/Safe.multisig.3owners1threshold.test.js @@ -0,0 +1,75 @@ +// @flow +import * as React from 'react' +import TestUtils from 'react-dom/test-utils' +import { Provider } from 'react-redux' +import { ConnectedRouter } from 'react-router-redux' +import { aNewStore, history } from '~/store' +import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder' +import { SAFELIST_ADDRESS } from '~/routes/routes' +import AppRoutes from '~/routes' +import AddTransactionComponent from '~/routes/safe/component/AddTransaction' +import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index' +import { createMultisigTxFilling, addFundsTo, checkBalanceOf, listTxsOf, getTagFromTransaction, expandTransactionOf } from '~/routes/safe/test/testMultisig' + +const renderSafe = localStore => ( + TestUtils.renderIntoDocument(( + + + + + + )) +) + +describe('React DOM TESTS > Multisig transactions from safe [3 owners & 1 threshold] ', () => { + let SafeDom + let store + let address + beforeEach(async () => { + // create store + store = aNewStore() + // deploy safe updating store + address = await aDeployedSafe(store, 10, 1, 3) + // navigate to SAFE route + history.push(`${SAFELIST_ADDRESS}/${address}`) + SafeDom = renderSafe(store) + }) + + const getTransactionFromReduxStore = () => { + const transactions = safeTransactionsSelector(store.getState(), { safeAddress: address }) + + return transactions.get(0) + } + + const confirmOwners = async (...statusses: string[]) => { + const paragraphsWithOwners = getTagFromTransaction(SafeDom, 'h3') + for (let i = 0; i < statusses.length; i += 1) { + const ownerIndex = i + 6 + const ownerParagraph = paragraphsWithOwners[ownerIndex].innerHTML + expect(statusses[i]).toEqual(ownerParagraph) + } + } + + it('should execute transaction after 2 owners have confirmed and the last one executed correctly', async () => { + await addFundsTo(SafeDom, address) + await checkBalanceOf(address, '0.1') + await createMultisigTxFilling(SafeDom, AddTransactionComponent, store) + await checkBalanceOf(address, '0.09') + await listTxsOf(SafeDom) + + await expandTransactionOf(SafeDom, 3) + await confirmOwners('Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Not confirmed]', 'Adolfo 3 Eth Account [Not confirmed]') + + const paragraphs = getTagFromTransaction(SafeDom, 'p') + + const status = paragraphs[2].innerHTML + expect(status).toBe('Already executed') + + const confirmed = paragraphs[3].innerHTML + const tx = getTransactionFromReduxStore() + expect(confirmed).toBe(tx.get('tx')) + + const ownerTx = paragraphs[6].innerHTML + expect(ownerTx).toBe('Confirmation hash: EXECUTED') + }) +}) diff --git a/src/routes/safe/component/Safe.multisig.txs.test.js b/src/routes/safe/test/Safe.multisig.3owners3threshold.test.js similarity index 100% rename from src/routes/safe/component/Safe.multisig.txs.test.js rename to src/routes/safe/test/Safe.multisig.3owners3threshold.test.js diff --git a/src/routes/safe/component/Safe.withdrawn.test.js b/src/routes/safe/test/Safe.withdrawn.test.js similarity index 100% rename from src/routes/safe/component/Safe.withdrawn.test.js rename to src/routes/safe/test/Safe.withdrawn.test.js From ddf43fc60af4b94ccf218f3245c5f9a693883630 Mon Sep 17 00:00:00 2001 From: apanizo Date: Mon, 4 Jun 2018 10:21:50 +0200 Subject: [PATCH 4/4] WA-238 Refactoring 3 owners 3 threshold DOM test --- .../Safe.multisig.3owners1threshold.test.js | 24 +--- .../Safe.multisig.3owners3threshold.test.js | 127 +++--------------- src/routes/safe/test/testMultisig.js | 20 ++- 3 files changed, 41 insertions(+), 130 deletions(-) diff --git a/src/routes/safe/test/Safe.multisig.3owners1threshold.test.js b/src/routes/safe/test/Safe.multisig.3owners1threshold.test.js index d8cad9284f..4b1c7a47fb 100644 --- a/src/routes/safe/test/Safe.multisig.3owners1threshold.test.js +++ b/src/routes/safe/test/Safe.multisig.3owners1threshold.test.js @@ -8,8 +8,7 @@ import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.bui import { SAFELIST_ADDRESS } from '~/routes/routes' import AppRoutes from '~/routes' import AddTransactionComponent from '~/routes/safe/component/AddTransaction' -import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index' -import { createMultisigTxFilling, addFundsTo, checkBalanceOf, listTxsOf, getTagFromTransaction, expandTransactionOf } from '~/routes/safe/test/testMultisig' +import { createMultisigTxFilling, addFundsTo, checkBalanceOf, listTxsOf, getTagFromTransaction, expandTransactionOf, getTransactionFromReduxStore, confirmOwners } from '~/routes/safe/test/testMultisig' const renderSafe = localStore => ( TestUtils.renderIntoDocument(( @@ -35,21 +34,6 @@ describe('React DOM TESTS > Multisig transactions from safe [3 owners & 1 thresh SafeDom = renderSafe(store) }) - const getTransactionFromReduxStore = () => { - const transactions = safeTransactionsSelector(store.getState(), { safeAddress: address }) - - return transactions.get(0) - } - - const confirmOwners = async (...statusses: string[]) => { - const paragraphsWithOwners = getTagFromTransaction(SafeDom, 'h3') - for (let i = 0; i < statusses.length; i += 1) { - const ownerIndex = i + 6 - const ownerParagraph = paragraphsWithOwners[ownerIndex].innerHTML - expect(statusses[i]).toEqual(ownerParagraph) - } - } - it('should execute transaction after 2 owners have confirmed and the last one executed correctly', async () => { await addFundsTo(SafeDom, address) await checkBalanceOf(address, '0.1') @@ -57,8 +41,8 @@ describe('React DOM TESTS > Multisig transactions from safe [3 owners & 1 thresh await checkBalanceOf(address, '0.09') await listTxsOf(SafeDom) - await expandTransactionOf(SafeDom, 3) - await confirmOwners('Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Not confirmed]', 'Adolfo 3 Eth Account [Not confirmed]') + await expandTransactionOf(SafeDom, 3, 1) + await confirmOwners(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Not confirmed]', 'Adolfo 3 Eth Account [Not confirmed]') const paragraphs = getTagFromTransaction(SafeDom, 'p') @@ -66,7 +50,7 @@ describe('React DOM TESTS > Multisig transactions from safe [3 owners & 1 thresh expect(status).toBe('Already executed') const confirmed = paragraphs[3].innerHTML - const tx = getTransactionFromReduxStore() + const tx = getTransactionFromReduxStore(store, address) expect(confirmed).toBe(tx.get('tx')) const ownerTx = paragraphs[6].innerHTML diff --git a/src/routes/safe/test/Safe.multisig.3owners3threshold.test.js b/src/routes/safe/test/Safe.multisig.3owners3threshold.test.js index 8784e2fee6..8a96b50bd0 100644 --- a/src/routes/safe/test/Safe.multisig.3owners3threshold.test.js +++ b/src/routes/safe/test/Safe.multisig.3owners3threshold.test.js @@ -3,23 +3,18 @@ import * as React from 'react' import TestUtils from 'react-dom/test-utils' import { Provider } from 'react-redux' import { ConnectedRouter } from 'react-router-redux' -import Button from '~/components/layout/Button' import { aNewStore, history } from '~/store' -import { addEtherTo } from '~/test/addEtherTo' import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder' import { SAFELIST_ADDRESS } from '~/routes/routes' -import SafeView from '~/routes/safe/component/Safe' import AppRoutes from '~/routes' -import { getBalanceInEtherOf, getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/wallets/getWeb3' import { sleep } from '~/utils/timer' -import { ADD_MULTISIG_BUTTON_TEXT, SEE_MULTISIG_BUTTON_TEXT } from '~/routes/safe/component/Safe/MultisigTx' -import AddTransactionComponent from '~/routes/safe/component/AddTransaction' -import TransactionsComponent from '~/routes/safe/component/Transactions' -import TransactionComponent from '~/routes/safe/component/Transactions/Transaction' import { promisify } from '~/utils/promisify' +import AddTransactionComponent from '~/routes/safe/component/AddTransaction' import { processTransaction } from '~/routes/safe/component/Transactions/processTransactions' -import { safeTransactionsSelector, confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index' +import { confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' +import { createMultisigTxFilling, addFundsTo, checkBalanceOf, listTxsOf, getTagFromTransaction, expandTransactionOf, getTransactionFromReduxStore, confirmOwners } from '~/routes/safe/test/testMultisig' const renderSafe = localStore => ( TestUtils.renderIntoDocument(( @@ -47,121 +42,37 @@ describe('React DOM TESTS > Multisig transactions from safe [3 owners & 3 thresh accounts = await promisify(cb => getWeb3().eth.getAccounts(cb)) }) - const listTxs = () => { - const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView) - - // $FlowFixMe - const buttons = TestUtils.scryRenderedComponentsWithType(Safe, Button) - const seeTx = buttons[2] - expect(seeTx.props.children).toEqual(SEE_MULTISIG_BUTTON_TEXT) - TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(seeTx, 'button')[0]) - } - - const createMultisigTxFilling = async () => { - // Get AddTransaction form component - const AddTransaction = TestUtils.findRenderedComponentWithType(SafeDom, AddTransactionComponent) - - // $FlowFixMe - const inputs = TestUtils.scryRenderedDOMComponentsWithTag(AddTransaction, 'input') - const name = inputs[0] - const destination = inputs[1] - const amountInEth = inputs[2] - TestUtils.Simulate.change(name, { target: { value: 'Buying betteries' } }) - TestUtils.Simulate.change(amountInEth, { target: { value: '0.01' } }) - TestUtils.Simulate.change(destination, { target: { value: store.getState().providers.account } }) - - // $FlowFixMe - const form = TestUtils.findRenderedDOMComponentWithTag(AddTransaction, 'form') - - TestUtils.Simulate.submit(form) // fill the form - TestUtils.Simulate.submit(form) // confirming data - return sleep(4000) - } - - const checkBalanceOf = async (addressToTest: string, value: string) => { - const safeBalance = await getBalanceInEtherOf(addressToTest) - expect(safeBalance).toBe(value) - } - - const addFundsTo = async (destination: string) => { - // add funds to safe - await addEtherTo(destination, '0.1') - const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView) - - // $FlowFixMe - const buttons = TestUtils.scryRenderedComponentsWithType(Safe, Button) - const addTxButton = buttons[1] - expect(addTxButton.props.children).toEqual(ADD_MULTISIG_BUTTON_TEXT) - await sleep(1800) // Give time to enable Add button - TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(addTxButton, 'button')[0]) - } - - const getTransactionFromReduxStore = () => { - const transactions = safeTransactionsSelector(store.getState(), { safeAddress: address }) - - return transactions.get(0) - } const getAlreadyConfirmed = () => { - const tx = getTransactionFromReduxStore() + const tx = getTransactionFromReduxStore(store, address) const confirmed = confirmationsTransactionSelector(store.getState(), { transaction: tx }) return confirmed } - const getTagFromTransaction = (tag: string) => { - const Transactions = TestUtils.findRenderedComponentWithType(SafeDom, TransactionsComponent) - if (!Transactions) throw new Error() - const Transaction = TestUtils.findRenderedComponentWithType(Transactions, TransactionComponent) - if (!Transaction) throw new Error() - - return TestUtils.scryRenderedDOMComponentsWithTag(Transaction, tag) - } - - const expandTransactionOf = async (numOwners) => { - const paragraphs = getTagFromTransaction('p') - TestUtils.Simulate.click(paragraphs[2]) // expanded - await sleep(1000) // Time to expand - const paragraphsExpanded = getTagFromTransaction('p') - const threshold = paragraphsExpanded[5] - expect(threshold.innerHTML).toContain('confirmations needed') - TestUtils.Simulate.click(threshold) // expanded - await sleep(1000) // Time to expand - expect(paragraphsExpanded.length).toBe(paragraphs.length + numOwners) - } - - const confirmOwners = async (...statusses: string[]) => { - const paragraphsWithOwners = getTagFromTransaction('h3') - for (let i = 0; i < statusses.length; i += 1) { - const ownerIndex = i + 6 - const ownerParagraph = paragraphsWithOwners[ownerIndex].innerHTML - expect(statusses[i]).toEqual(ownerParagraph) - } - } - const makeConfirmation = async (executor) => { const alreadyConfirmed = getAlreadyConfirmed() - const tx = getTransactionFromReduxStore() + const tx = getTransactionFromReduxStore(store, address) await processTransaction(address, tx, alreadyConfirmed, executor) await sleep(800) store.dispatch(fetchTransactions()) sleep(1800) SafeDom = renderSafe(store) sleep(1800) - await listTxs() + await listTxsOf(SafeDom) sleep(800) - await expandTransactionOf(3) + await expandTransactionOf(SafeDom, 3, 3) sleep(800) } it('should execute transaction after 2 owners have confirmed and the last one executed correctly', async () => { - await addFundsTo(address) - await createMultisigTxFilling() + await addFundsTo(SafeDom, address) + await createMultisigTxFilling(SafeDom, AddTransactionComponent, store) await checkBalanceOf(address, '0.1') - await listTxs() - - const paragraphs = getTagFromTransaction('p') + await listTxsOf(SafeDom) + sleep(800) + const paragraphs = getTagFromTransaction(SafeDom, 'p') const status = paragraphs[2].innerHTML expect(status).toBe('1 of the 3 confirmations needed') @@ -169,22 +80,22 @@ describe('React DOM TESTS > Multisig transactions from safe [3 owners & 3 thresh const confirmed = paragraphs[3].innerHTML expect(confirmed).toBe('Waiting for the rest of confirmations') - await expandTransactionOf(3) - await confirmOwners('Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Not confirmed]', 'Adolfo 3 Eth Account [Not confirmed]') + await expandTransactionOf(SafeDom, 3, 3) + await confirmOwners(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Not confirmed]', 'Adolfo 3 Eth Account [Not confirmed]') await makeConfirmation(accounts[1]) - await confirmOwners('Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Not confirmed]') + await confirmOwners(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Not confirmed]') await makeConfirmation(accounts[2]) - await confirmOwners('Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Confirmed]') + await confirmOwners(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Confirmed]') - const paragraphsExecuted = getTagFromTransaction('p') + const paragraphsExecuted = getTagFromTransaction(SafeDom, 'p') const statusExecuted = paragraphsExecuted[2].innerHTML expect(statusExecuted).toBe('Already executed') const confirmedExecuted = paragraphsExecuted[3].innerHTML - const tx = getTransactionFromReduxStore() + const tx = getTransactionFromReduxStore(store, address) expect(confirmedExecuted).toBe(tx.get('tx')) }) }) diff --git a/src/routes/safe/test/testMultisig.js b/src/routes/safe/test/testMultisig.js index 0278af92c6..c4264cd523 100644 --- a/src/routes/safe/test/testMultisig.js +++ b/src/routes/safe/test/testMultisig.js @@ -8,6 +8,7 @@ import { addEtherTo } from '~/test/addEtherTo' import SafeView from '~/routes/safe/component/Safe' import TransactionsComponent from '~/routes/safe/component/Transactions' import TransactionComponent from '~/routes/safe/component/Transactions/Transaction' +import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index' export const createMultisigTxFilling = async (SafeDom, AddTransactionComponent, store) => { // Get AddTransaction form component @@ -67,14 +68,29 @@ export const getTagFromTransaction = (SafeDom, tag: string) => { return TestUtils.scryRenderedDOMComponentsWithTag(Transaction, tag) } -export const expandTransactionOf = async (SafeDom, numOwners) => { +export const expandTransactionOf = async (SafeDom, numOwners, safeThreshold) => { const paragraphs = getTagFromTransaction(SafeDom, 'p') TestUtils.Simulate.click(paragraphs[2]) // expanded await sleep(1000) // Time to expand const paragraphsExpanded = getTagFromTransaction(SafeDom, 'p') const threshold = paragraphsExpanded[5] - expect(threshold.innerHTML).toContain(`confirmation${numOwners === 1 ? 's' : ''} needed`) + expect(threshold.innerHTML).toContain(`confirmation${safeThreshold === 1 ? '' : 's'} needed`) TestUtils.Simulate.click(threshold) // expanded await sleep(1000) // Time to expand expect(paragraphsExpanded.length).toBe(paragraphs.length + numOwners) } + +export const getTransactionFromReduxStore = (store, address) => { + const transactions = safeTransactionsSelector(store.getState(), { safeAddress: address }) + + return transactions.get(0) +} + +export const confirmOwners = async (SafeDom, ...statusses: string[]) => { + const paragraphsWithOwners = getTagFromTransaction(SafeDom, 'h3') + for (let i = 0; i < statusses.length; i += 1) { + const ownerIndex = i + 6 + const ownerParagraph = paragraphsWithOwners[ownerIndex].innerHTML + expect(statusses[i]).toEqual(ownerParagraph) + } +}