WA-232 Refactor safe tests improving its speed

This commit is contained in:
apanizo 2018-06-29 17:39:09 +02:00
parent bb566def6a
commit 477e7002f3
8 changed files with 122 additions and 436 deletions

View File

@ -1,103 +0,0 @@
// @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/utils/tokenMovements'
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 AddTransactionComponent, { SEE_TXS_BUTTON_TEXT } from '~/routes/safe/component/AddTransaction'
import TransactionsComponent from '~/routes/safe/component/Transactions'
import TransactionComponent from '~/routes/safe/component/Transactions/Transaction'
import { getBalanceInEtherOf } from '~/wallets/getWeb3'
import { sleep } from '~/utils/timer'
import { ADD_MULTISIG_BUTTON_TEXT } from '~/routes/safe/component/Safe/MultisigTx'
import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index'
import { MOVE_FUNDS_INDEX } from '~/test/builder/safe.dom.utils'
describe('React DOM TESTS > Withdraw funds from safe', () => {
let SafeDom
let store
let address
beforeEach(async () => {
// create store
store = aNewStore()
// deploy safe updating store
address = await aDeployedSafe(store)
// navigate to SAFE route
history.push(`${SAFELIST_ADDRESS}/${address}`)
SafeDom = TestUtils.renderIntoDocument((
<Provider store={store}>
<ConnectedRouter history={history}>
<AppRoutes />
</ConnectedRouter>
</Provider>
))
})
it('should execute one transaction if safe has only one owner', async () => {
// add funds to safe
await addEtherTo(address, '0.1')
const Safe = TestUtils.findRenderedComponentWithType(SafeDom, SafeView)
// $FlowFixMe
const buttons = TestUtils.scryRenderedDOMComponentsWithTag(Safe, 'button')
const addTxButton = buttons[MOVE_FUNDS_INDEX]
expect(addTxButton.getElementsByTagName('span')[0].innerHTML).toEqual(ADD_MULTISIG_BUTTON_TEXT)
await sleep(1800) // Give time to enable Add button
TestUtils.Simulate.click(addTxButton)
await sleep(1800) // Give time to render the form
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
await sleep(4000)
const safeBalance = await getBalanceInEtherOf(address)
expect(safeBalance).toBe('0.09')
// $FlowFixMe
const addTransactionButtons = TestUtils.scryRenderedComponentsWithType(AddTransaction, Button)
expect(addTransactionButtons.length).toBe(1)
const visitTxsButton = addTransactionButtons[0]
expect(visitTxsButton.props.children).toEqual(SEE_TXS_BUTTON_TEXT)
// NOW it is time to check the just executed transaction
TestUtils.Simulate.click(TestUtils.scryRenderedDOMComponentsWithTag(visitTxsButton, 'button')[0])
const Transactions = TestUtils.findRenderedComponentWithType(SafeDom, TransactionsComponent)
if (!Transactions) throw new Error()
const Transaction = TestUtils.findRenderedComponentWithType(Transactions, TransactionComponent)
if (!Transaction) throw new Error()
const paragraphs = TestUtils.scryRenderedDOMComponentsWithTag(Transaction, 'p')
expect(paragraphs[2].innerHTML).toBe('Already executed')
TestUtils.Simulate.click(paragraphs[2]) // expanded
await sleep(1000) // Time to expand
const paragraphsExpanded = TestUtils.scryRenderedDOMComponentsWithTag(Transaction, 'p')
const txHashParagraph = paragraphsExpanded[3]
const transactions = safeTransactionsSelector(store.getState(), { safeAddress: address })
const batteryTx = transactions.get(0)
if (!batteryTx) throw new Error()
expect(txHashParagraph.innerHTML).toBe(batteryTx.get('tx'))
})
})

View File

@ -1,62 +0,0 @@
// @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, getListItemsFrom, expandTransactionOf, getTransactionFromReduxStore, confirmOwners } from '~/routes/safe/test/testMultisig'
import { sleep } from '~/utils/timer'
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 straight away', async () => {
await addFundsTo(SafeDom, address)
await checkBalanceOf(address, '0.1')
await createMultisigTxFilling(SafeDom, AddTransactionComponent, store)
await checkBalanceOf(address, '0.09')
await listTxsOf(SafeDom)
await sleep(2500)
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 listItems = getListItemsFrom(SafeDom)
const status = listItems[2].props.secondary
expect(status).toBe('Already executed')
const confirmed = listItems[3].props.secondary
const tx = getTransactionFromReduxStore(store, address)
if (!tx) throw new Error()
expect(confirmed).toBe(tx.get('tx'))
const ownerTx = listItems[6].props.secondary
expect(ownerTx).toBe('Confirmation hash: EXECUTED')
})
})

View File

@ -1,104 +0,0 @@
// @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, getListItemsFrom, 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)
if (!tx) throw new Error()
const confirmed = confirmationsTransactionSelector(store.getState(), { transaction: tx })
return confirmed
}
const makeConfirmation = async (executor) => {
const alreadyConfirmed = getAlreadyConfirmed()
const tx = getTransactionFromReduxStore(store, address)
if (!tx) throw new Error()
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(1400)
const listItems = getListItemsFrom(SafeDom)
const status = listItems[2].props.secondary
expect(status).toBe('1 of the 3 confirmations needed')
const confirmed = listItems[3].props.secondary
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 listItemsExecuted = getListItemsFrom(SafeDom)
const statusExecuted = listItemsExecuted[2].props.secondary
expect(statusExecuted).toBe('Already executed')
const confirmedExecuted = listItemsExecuted[3].props.secondary
const tx = getTransactionFromReduxStore(store, address)
if (!tx) throw new Error()
expect(confirmedExecuted).toBe(tx.get('tx'))
})
})

View File

@ -1,74 +0,0 @@
// @flow
import TestUtils from 'react-dom/test-utils'
import { store } from '~/store'
import {
FIELD_NAME,
FIELD_OWNERS,
FIELD_CONFIRMATIONS,
FIELD_DAILY_LIMIT,
getOwnerNameBy,
getOwnerAddressBy,
} from '~/routes/open/components/fields'
import { DEPLOYED_COMPONENT_ID } from '~/routes/open/components/FormConfirmation'
import { sleep } from '~/utils/timer'
import { getProviderInfo } from '~/wallets/getWeb3'
import { renderSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder'
describe('React DOM TESTS > Create Safe form', () => {
let open
let provider
beforeEach(async () => {
provider = await getProviderInfo()
open = await renderSafe(store)
})
it('should create a 1 owner safe after rendering correctly the form', async () => {
const inputs = TestUtils.scryRenderedDOMComponentsWithTag(open, 'input')
const fieldName = inputs[0]
expect(fieldName.name).toEqual(FIELD_NAME)
const fieldOwners = inputs[1]
expect(fieldOwners.name).toEqual(FIELD_OWNERS)
const fieldConfirmations = inputs[2]
expect(fieldConfirmations.name).toEqual(FIELD_CONFIRMATIONS)
const dailyLimitConfirmations = inputs[3]
expect(dailyLimitConfirmations.name).toEqual(FIELD_DAILY_LIMIT)
TestUtils.Simulate.change(fieldOwners, { target: { value: '1' } })
const inputsExpanded = TestUtils.scryRenderedDOMComponentsWithTag(open, 'input')
const ownerName = inputsExpanded[2]
expect(ownerName.name).toEqual(getOwnerNameBy(0))
const ownerAddress = inputsExpanded[3]
expect(ownerAddress.name).toEqual(getOwnerAddressBy(0))
expect(ownerAddress.value).toEqual(provider.account)
// WHEN
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(dailyLimitConfirmations, { target: { value: '10' } })
const form = TestUtils.findRenderedDOMComponentWithTag(open, 'form')
// One submit per step when creating a safe
TestUtils.Simulate.submit(form) // fill the form
TestUtils.Simulate.submit(form) // confirming data
TestUtils.Simulate.submit(form) // Executing transaction
// giving some time to the component for updating its state with safe
// before destroying its context
await sleep(9000)
// THEN
const deployed = TestUtils.findRenderedDOMComponentWithClass(open, DEPLOYED_COMPONENT_ID)
if (deployed) {
const transaction = JSON.parse(deployed.getElementsByTagName('pre')[0].innerHTML)
delete transaction.receipt.logsBloom
// eslint-disable-next-line
// console.log(transaction)
}
})
})

View File

@ -4,98 +4,15 @@ import { type Store } from 'redux'
import TestUtils from 'react-dom/test-utils'
import { Provider } from 'react-redux'
import { ConnectedRouter } from 'react-router-redux'
import { DEPLOYED_COMPONENT_ID } from '~/routes/open/components/FormConfirmation'
import Open from '~/routes/open/container/Open'
import SafeView from '~/routes/safe/component/Safe'
import { aNewStore, history, type GlobalState } from '~/store'
import { sleep } from '~/utils/timer'
import { getProviderInfo, getWeb3 } from '~/wallets/getWeb3'
import addProvider from '~/wallets/store/actions/addProvider'
import { makeProvider } from '~/wallets/store/model/provider'
import { getWeb3 } from '~/wallets/getWeb3'
import AppRoutes from '~/routes'
import { SAFELIST_ADDRESS } from '~/routes/routes'
import { promisify } from '~/utils/promisify'
import { addEtherTo } from '~/test/utils/tokenMovements'
const fillOpenSafeForm = async (localStore: Store<GlobalState>) => {
const provider = await getProviderInfo()
const walletRecord = makeProvider(provider)
localStore.dispatch(addProvider(walletRecord))
return (
TestUtils.renderIntoDocument((
<Provider store={localStore}>
<ConnectedRouter history={history}>
<Open />
</ConnectedRouter>
</Provider>
))
)
}
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]
const web3 = getWeb3()
const accounts = await promisify(cb => web3.eth.getAccounts(cb))
TestUtils.Simulate.change(fieldOwners, { target: { value: `${numOwners}` } })
await sleep(1500)
const inputsExpanded = TestUtils.scryRenderedDOMComponentsWithTag(safe, 'input')
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: `${threshold}` } })
TestUtils.Simulate.change(fieldDailyLimit, { target: { value: dailyLimit } })
const form = TestUtils.findRenderedDOMComponentWithTag(safe, 'form')
TestUtils.Simulate.submit(form) // fill the form
TestUtils.Simulate.submit(form) // confirming data
TestUtils.Simulate.submit(form) // Executing transaction
// giving some time to the component for updating its state with safe
// before destroying its context
await sleep(15000)
// THEN
const deployed = TestUtils.findRenderedDOMComponentWithClass(safe, DEPLOYED_COMPONENT_ID)
if (!deployed) {
throw new Error()
}
const transactionHash = JSON.parse(deployed.getElementsByTagName('pre')[0].innerHTML)
delete transactionHash.receipt.logsBloom
return transactionHash
}
const aDeployedSafe = async (
specificStore: Store<GlobalState>,
dailyLimit?: number = 0.5,
threshold?: number = 1,
numOwners?: number = 1,
) => {
const safe: React$Component<{}> = await fillOpenSafeForm(specificStore)
const deployedSafe = await deploySafe(safe, `${dailyLimit}`, threshold, numOwners)
return deployedSafe.logs[1].args.proxy
}
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
export type DomSafe = {
address: string,
@ -106,14 +23,14 @@ export type DomSafe = {
}
export const renderSafeInDom = async (
owners: number,
threshold: number,
owners: number = 1,
threshold: number = 1,
dailyLimit: number = 0.5,
): Promise<DomSafe> => {
// create store
const store = aNewStore()
// deploy safe updating store
const address = await aDeployedSafe(store, dailyLimit, threshold, owners)
const address = await aMinedSafe(store, owners, threshold, dailyLimit)
// have available accounts
const accounts = await promisify(cb => getWeb3().eth.getAccounts(cb))
// navigate to SAFE route

View File

@ -83,7 +83,12 @@ export class SafeFactory {
.get()
}
export const aMinedSafe = async (store: Store<GlobalState>): Promise<string> => {
export const aMinedSafe = async (
store: Store<GlobalState>,
owners: number = 1,
threshold: number = 1,
dailyLimit: number = 0.5,
): Promise<string> => {
const provider = await getProviderInfo()
const walletRecord = makeProvider(provider)
store.dispatch(addProvider(walletRecord))
@ -91,11 +96,11 @@ export const aMinedSafe = async (store: Store<GlobalState>): Promise<string> =>
const accounts = await promisify(cb => getWeb3().eth.getAccounts(cb))
const form = {
[FIELD_NAME]: 'Safe Name',
[FIELD_CONFIRMATIONS]: '1',
[FIELD_OWNERS]: '1',
[getOwnerNameBy(0)]: 'Adol Metamask 1',
[FIELD_CONFIRMATIONS]: `${threshold}`,
[FIELD_OWNERS]: `${owners}`,
[getOwnerNameBy(0)]: 'Adolfo 1 Eth Account',
[getOwnerAddressBy(0)]: accounts[0],
[FIELD_DAILY_LIMIT]: '5',
[FIELD_DAILY_LIMIT]: `${dailyLimit}`,
}
const addSafeFn: any = (...args) => store.dispatch(addSafe(...args))

View File

@ -0,0 +1,107 @@
// @flow
import * as React from 'react'
import { type Store } from 'redux'
import TestUtils from 'react-dom/test-utils'
import { Provider } from 'react-redux'
import { ConnectedRouter } from 'react-router-redux'
import { DEPLOYED_COMPONENT_ID } from '~/routes/open/components/FormConfirmation'
import Open from '~/routes/open/container/Open'
import { aNewStore, history, type GlobalState } from '~/store'
import { sleep } from '~/utils/timer'
import { getProviderInfo, getWeb3 } from '~/wallets/getWeb3'
import addProvider from '~/wallets/store/actions/addProvider'
import { makeProvider } from '~/wallets/store/model/provider'
import { promisify } from '~/utils/promisify'
const fillOpenSafeForm = async (localStore: Store<GlobalState>) => {
const provider = await getProviderInfo()
const walletRecord = makeProvider(provider)
localStore.dispatch(addProvider(walletRecord))
return (
TestUtils.renderIntoDocument((
<Provider store={localStore}>
<ConnectedRouter history={history}>
<Open />
</ConnectedRouter>
</Provider>
))
)
}
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]
const web3 = getWeb3()
const accounts = await promisify(cb => web3.eth.getAccounts(cb))
TestUtils.Simulate.change(fieldOwners, { target: { value: `${numOwners}` } })
await sleep(1500)
const inputsExpanded = TestUtils.scryRenderedDOMComponentsWithTag(safe, 'input')
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: `${threshold}` } })
TestUtils.Simulate.change(fieldDailyLimit, { target: { value: dailyLimit } })
const form = TestUtils.findRenderedDOMComponentWithTag(safe, 'form')
TestUtils.Simulate.submit(form) // fill the form
TestUtils.Simulate.submit(form) // confirming data
TestUtils.Simulate.submit(form) // Executing transaction
// giving some time to the component for updating its state with safe
// before destroying its context
await sleep(8000)
// THEN
const deployed = TestUtils.findRenderedDOMComponentWithClass(safe, DEPLOYED_COMPONENT_ID)
if (!deployed) {
throw new Error()
}
const transactionHash = JSON.parse(deployed.getElementsByTagName('pre')[0].innerHTML)
delete transactionHash.receipt.logsBloom
return transactionHash
}
const aDeployedSafe = async (
specificStore: Store<GlobalState>,
dailyLimit?: number = 0.5,
threshold?: number = 1,
numOwners?: number = 1,
) => {
const safe: React$Component<{}> = await fillOpenSafeForm(specificStore)
const deployedSafe = await deploySafe(safe, `${dailyLimit}`, threshold, numOwners)
return deployedSafe.logs[1].args.proxy
}
describe('DOM > Feature > CREATE a safe', () => {
it('fills correctly the safe form with 4 owners, 4 threshold and 5 ETH as daily limit', async () => {
const owners = 4
const threshold = 4
const dailyLimit = 5
const store = aNewStore()
const address = await aDeployedSafe(store, dailyLimit, threshold, owners)
expect(address).not.toBe(null)
expect(address).not.toBe(undefined)
})
})