Skip to content
This repository was archived by the owner on Nov 10, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions src/routes/safe/store/test/builder/deployedSafe.builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -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<GlobalState>) => {
const provider = await getProviderInfo()
Expand All @@ -29,20 +30,34 @@ export const renderSafe = async (localStore: Store<GlobalState>) => {
)
}

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')
Expand All @@ -67,9 +82,14 @@ const deploySafe = async (safe: React$Component<{}>, dailyLimit: string) => {
return transactionHash
}

export const aDeployedSafe = async (specificStore: Store<GlobalState>, dailyLimit?: number = 0.5) => {
export const aDeployedSafe = async (
specificStore: Store<GlobalState>,
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
}
Expand Down
59 changes: 59 additions & 0 deletions src/routes/safe/test/Safe.multisig.3owners1threshold.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// @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 { createMultisigTxFilling, addFundsTo, checkBalanceOf, listTxsOf, getTagFromTransaction, expandTransactionOf, getTransactionFromReduxStore, confirmOwners } from '~/routes/safe/test/testMultisig'

const renderSafe = localStore => (
TestUtils.renderIntoDocument((
<Provider store={localStore}>
<ConnectedRouter history={history}>
<AppRoutes />
</ConnectedRouter>
</Provider>
))
)

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)
})

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, 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')

const status = paragraphs[2].innerHTML
expect(status).toBe('Already executed')

const confirmed = paragraphs[3].innerHTML
const tx = getTransactionFromReduxStore(store, address)
expect(confirmed).toBe(tx.get('tx'))

const ownerTx = paragraphs[6].innerHTML
expect(ownerTx).toBe('Confirmation hash: EXECUTED')
})
})
101 changes: 101 additions & 0 deletions src/routes/safe/test/Safe.multisig.3owners3threshold.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// @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 { getWeb3 } from '~/wallets/getWeb3'
import { sleep } from '~/utils/timer'
import { promisify } from '~/utils/promisify'
import AddTransactionComponent from '~/routes/safe/component/AddTransaction'
import { processTransaction } from '~/routes/safe/component/Transactions/processTransactions'
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((
<Provider store={localStore}>
<ConnectedRouter history={history}>
<AppRoutes />
</ConnectedRouter>
</Provider>
))
)

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 getAlreadyConfirmed = () => {
const tx = getTransactionFromReduxStore(store, address)
const confirmed = confirmationsTransactionSelector(store.getState(), { transaction: tx })

return confirmed
}

const makeConfirmation = async (executor) => {
const alreadyConfirmed = getAlreadyConfirmed()
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 listTxsOf(SafeDom)
sleep(800)
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(SafeDom, address)
await createMultisigTxFilling(SafeDom, AddTransactionComponent, store)

await checkBalanceOf(address, '0.1')
await listTxsOf(SafeDom)
sleep(800)
const paragraphs = getTagFromTransaction(SafeDom, '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(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(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Not confirmed]')

await makeConfirmation(accounts[2])
await confirmOwners(SafeDom, 'Adolfo 1 Eth Account [Confirmed]', 'Adolfo 2 Eth Account [Confirmed]', 'Adolfo 3 Eth Account [Confirmed]')

const paragraphsExecuted = getTagFromTransaction(SafeDom, 'p')

const statusExecuted = paragraphsExecuted[2].innerHTML
expect(statusExecuted).toBe('Already executed')

const confirmedExecuted = paragraphsExecuted[3].innerHTML
const tx = getTransactionFromReduxStore(store, address)
expect(confirmedExecuted).toBe(tx.get('tx'))
})
})
96 changes: 96 additions & 0 deletions src/routes/safe/test/testMultisig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// @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'
import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index'

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, 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${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)
}
}