From bf174d6f94599fcd8345d622bb45bd5cd22e181f Mon Sep 17 00:00:00 2001 From: mmv Date: Mon, 3 Jun 2019 16:49:52 +0400 Subject: [PATCH] refactor send ETH test --- build/contracts/DevDependenciesGetter.json | 2 +- build/contracts/GnosisMath.json | 2 +- build/contracts/GnosisStandardToken.json | 2 +- build/contracts/Migrations.json | 2 +- build/contracts/Proxied.json | 2 +- build/contracts/Proxy.json | 2 +- build/contracts/StandardTokenData.json | 2 +- build/contracts/Token.json | 2 +- build/contracts/TokenOMG.json | 2 +- build/contracts/TokenRDN.json | 2 +- package.json | 9 +- src/components/Header/index.jsx | 2 +- src/components/SharedSnackBar/Context.jsx | 67 ----------- src/components/SharedSnackBar/index.jsx | 68 +++++++++++- src/components/layout/PageFrame/index.jsx | 2 +- .../SendModal/screens/ReviewTx/index.jsx | 3 +- .../SendModal/screens/SendFunds/index.jsx | 9 +- src/store/index.js | 13 +-- src/test/builder/safe.dom.utils.js | 45 ++++---- src/test/safe.dom.funds.test.js | 69 +++++++----- src/test/safe.dom.tokens.test.js | 73 ++++++++++++ src/test/utils/tokenMovements.js | 11 +- yarn.lock | 104 ++++++++++++------ 23 files changed, 311 insertions(+), 184 deletions(-) delete mode 100644 src/components/SharedSnackBar/Context.jsx create mode 100644 src/test/safe.dom.tokens.test.js diff --git a/build/contracts/DevDependenciesGetter.json b/build/contracts/DevDependenciesGetter.json index 77f80b7a..f4996baa 100644 --- a/build/contracts/DevDependenciesGetter.json +++ b/build/contracts/DevDependenciesGetter.json @@ -138,7 +138,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.338Z", + "updatedAt": "2019-06-03T08:59:02.077Z", "devdoc": { "methods": {} }, diff --git a/build/contracts/GnosisMath.json b/build/contracts/GnosisMath.json index a8148fca..f02e538d 100644 --- a/build/contracts/GnosisMath.json +++ b/build/contracts/GnosisMath.json @@ -32319,7 +32319,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.349Z", + "updatedAt": "2019-06-03T08:59:02.114Z", "devdoc": { "author": "Alan Lu - Stefan George - ", "methods": { diff --git a/build/contracts/GnosisStandardToken.json b/build/contracts/GnosisStandardToken.json index da7e48c1..e5331808 100644 --- a/build/contracts/GnosisStandardToken.json +++ b/build/contracts/GnosisStandardToken.json @@ -5582,7 +5582,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.346Z", + "updatedAt": "2019-06-03T08:59:02.084Z", "devdoc": { "methods": { "allowance(address,address)": { diff --git a/build/contracts/Migrations.json b/build/contracts/Migrations.json index c6044c22..6a0e60ac 100644 --- a/build/contracts/Migrations.json +++ b/build/contracts/Migrations.json @@ -1369,7 +1369,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.344Z", + "updatedAt": "2019-06-03T08:59:02.080Z", "devdoc": { "methods": {} }, diff --git a/build/contracts/Proxied.json b/build/contracts/Proxied.json index 15e6e14e..016f4379 100644 --- a/build/contracts/Proxied.json +++ b/build/contracts/Proxied.json @@ -971,7 +971,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.362Z", + "updatedAt": "2019-06-03T08:59:02.136Z", "devdoc": { "author": "Alan Lu - ", "methods": {}, diff --git a/build/contracts/Proxy.json b/build/contracts/Proxy.json index 19d58dc3..5a25d765 100644 --- a/build/contracts/Proxy.json +++ b/build/contracts/Proxy.json @@ -987,7 +987,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.362Z", + "updatedAt": "2019-06-03T08:59:02.137Z", "devdoc": { "author": "Stefan George - ", "methods": { diff --git a/build/contracts/StandardTokenData.json b/build/contracts/StandardTokenData.json index 721a4480..64d7314a 100644 --- a/build/contracts/StandardTokenData.json +++ b/build/contracts/StandardTokenData.json @@ -5408,7 +5408,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.347Z", + "updatedAt": "2019-06-03T08:59:02.087Z", "devdoc": { "methods": {} }, diff --git a/build/contracts/Token.json b/build/contracts/Token.json index f858bea1..b6934a6b 100644 --- a/build/contracts/Token.json +++ b/build/contracts/Token.json @@ -1854,7 +1854,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.363Z", + "updatedAt": "2019-06-03T08:59:02.139Z", "devdoc": { "methods": {}, "title": "Abstract token contract - Functions to be implemented by token contracts" diff --git a/build/contracts/TokenOMG.json b/build/contracts/TokenOMG.json index cd77a240..c07180d9 100644 --- a/build/contracts/TokenOMG.json +++ b/build/contracts/TokenOMG.json @@ -953,7 +953,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.345Z", + "updatedAt": "2019-06-03T08:59:02.081Z", "devdoc": { "methods": { "allowance(address,address)": { diff --git a/build/contracts/TokenRDN.json b/build/contracts/TokenRDN.json index d729b6b8..c3fdf189 100644 --- a/build/contracts/TokenRDN.json +++ b/build/contracts/TokenRDN.json @@ -953,7 +953,7 @@ }, "networks": {}, "schemaVersion": "3.0.10", - "updatedAt": "2019-05-31T13:47:05.345Z", + "updatedAt": "2019-06-03T08:59:02.082Z", "devdoc": { "methods": { "allowance(address,address)": { diff --git a/package.json b/package.json index 08ad7a1e..263aeb16 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "axios": "0.19.0", "bignumber.js": "9.0.0", "connected-react-router": "^6.3.1", - "final-form": "4.13.0", + "final-form": "4.13.1", "history": "^4.7.2", "immortal-db": "^1.0.2", "immutable": "^4.0.0-rc.9", @@ -49,7 +49,7 @@ "react-dom": "^16.8.6", "react-final-form": "6.0.1", "react-final-form-listeners": "^1.0.2", - "react-hot-loader": "4.8.8", + "react-hot-loader": "4.9.0", "react-infinite-scroll-component": "^4.5.2", "react-redux": "7.0.3", "react-router-dom": "^4.3.1", @@ -112,11 +112,12 @@ "ethereumjs-abi": "^0.6.7", "extract-text-webpack-plugin": "^4.0.0-beta.0", "file-loader": "^3.0.1", - "flow-bin": "0.99.1", + "flow-bin": "0.100.0", "fs-extra": "8.0.1", "html-loader": "^0.5.5", "html-webpack-plugin": "^3.0.4", "jest": "24.8.0", + "jest-dom": "^3.4.0", "json-loader": "^0.5.7", "mini-css-extract-plugin": "0.7.0", "postcss-loader": "^3.0.0", @@ -135,7 +136,7 @@ "webpack": "4.32.2", "webpack-bundle-analyzer": "3.3.2", "webpack-cli": "3.3.2", - "webpack-dev-server": "3.4.1", + "webpack-dev-server": "3.5.1", "webpack-manifest-plugin": "^2.0.0-rc.2" } } diff --git a/src/components/Header/index.jsx b/src/components/Header/index.jsx index 4ff64c7f..6adfaeda 100644 --- a/src/components/Header/index.jsx +++ b/src/components/Header/index.jsx @@ -2,7 +2,7 @@ import * as React from 'react' import { connect } from 'react-redux' import { logComponentStack, type Info } from '~/utils/logBoundaries' -import { SharedSnackbarConsumer, type Variant } from '~/components/SharedSnackBar/Context' +import { SharedSnackbarConsumer, type Variant } from '~/components/SharedSnackBar' import { WALLET_ERROR_MSG } from '~/logic/wallets/store/actions' import ProviderAccesible from './component/ProviderInfo/ProviderAccesible' import UserDetails from './component/ProviderDetails/UserDetails' diff --git a/src/components/SharedSnackBar/Context.jsx b/src/components/SharedSnackBar/Context.jsx deleted file mode 100644 index 49ee43d4..00000000 --- a/src/components/SharedSnackBar/Context.jsx +++ /dev/null @@ -1,67 +0,0 @@ -// @flow -import * as React from 'react' -import SharedSnackBar from './index' - -const SharedSnackbarContext = React.createContext({ - openSnackbar: undefined, - closeSnackbar: undefined, - snackbarIsOpen: false, - message: '', - variant: 'info', -}) - -type Props = { - children: React$Node, -} - -export type Variant = 'success' | 'error' | 'warning' | 'info' - -type State = { - isOpen: boolean, - message: string, - variant: Variant, -} - -export class SharedSnackbarProvider extends React.Component { - state = { - isOpen: false, - message: '', - variant: 'info', - } - - openSnackbar = (message: string, variant: Variant) => { - this.setState({ - message, - variant, - isOpen: true, - }) - } - - closeSnackbar = () => { - this.setState({ - message: '', - isOpen: false, - }) - } - - render() { - const { children } = this.props - - return ( - - - {children} - - ) - } -} - -export const SharedSnackbarConsumer = SharedSnackbarContext.Consumer diff --git a/src/components/SharedSnackBar/index.jsx b/src/components/SharedSnackBar/index.jsx index 304021c0..1257c531 100644 --- a/src/components/SharedSnackBar/index.jsx +++ b/src/components/SharedSnackBar/index.jsx @@ -2,9 +2,8 @@ import * as React from 'react' import { Snackbar } from '@material-ui/core' import SnackbarContent from '~/components/SnackbarContent' -import { SharedSnackbarConsumer } from './Context' -const SharedSnackbar = () => ( +export const SharedSnackbar = () => ( {(value) => { const { @@ -32,4 +31,67 @@ const SharedSnackbar = () => ( ) -export default SharedSnackbar +const SharedSnackbarContext = React.createContext({ + openSnackbar: undefined, + closeSnackbar: undefined, + snackbarIsOpen: false, + message: '', + variant: 'info', +}) + +type Props = { + children: React$Node, +} + +export type Variant = 'success' | 'error' | 'warning' | 'info' + +type State = { + isOpen: boolean, + message: string, + variant: Variant, +} + +export class SharedSnackbarProvider extends React.Component { + state = { + isOpen: false, + message: '', + variant: 'info', + } + + openSnackbar = (message: string, variant: Variant) => { + this.setState({ + message, + variant, + isOpen: true, + }) + } + + closeSnackbar = () => { + this.setState({ + message: '', + isOpen: false, + }) + } + + render() { + const { children } = this.props + const { message, variant, isOpen } = this.state + + return ( + + + {children} + + ) + } +} + +export const SharedSnackbarConsumer = SharedSnackbarContext.Consumer diff --git a/src/components/layout/PageFrame/index.jsx b/src/components/layout/PageFrame/index.jsx index 28bf68f6..f64c4de9 100644 --- a/src/components/layout/PageFrame/index.jsx +++ b/src/components/layout/PageFrame/index.jsx @@ -2,7 +2,7 @@ import React from 'react' import Footer from '~/components/Footer' import Header from '~/components/Header' -import { SharedSnackbarProvider } from '~/components/SharedSnackBar/Context' +import { SharedSnackbarProvider } from '~/components/SharedSnackBar' import styles from './index.scss' type Props = { diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx index e3779478..3d2ac30a 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.jsx @@ -2,7 +2,7 @@ import React from 'react' import OpenInNew from '@material-ui/icons/OpenInNew' import { withStyles } from '@material-ui/core/styles' -import { SharedSnackbarConsumer } from '~/components/SharedSnackBar/Context' +import { SharedSnackbarConsumer } from '~/components/SharedSnackBar' import Close from '@material-ui/icons/Close' import IconButton from '@material-ui/core/IconButton' import Paragraph from '~/components/layout/Paragraph' @@ -124,6 +124,7 @@ const ReviewTx = ({ variant="contained" minWidth={140} color="primary" + data-testid="submit-tx-btn" > SUBMIT diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.jsx b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.jsx index 861499d5..33c9e25c 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.jsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.jsx @@ -161,7 +161,14 @@ const SendFunds = ({ - diff --git a/src/store/index.js b/src/store/index.js index e57c0435..b9703c0f 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,5 +1,5 @@ // @flow -import { createBrowserHistory } from 'history' +import { createBrowserHistory, createMemoryHistory } from 'history' import { connectRouter, routerMiddleware } from 'connected-react-router' import { combineReducers, createStore, applyMiddleware, compose, type Reducer, type Store, @@ -14,7 +14,7 @@ import transactions, { TRANSACTIONS_REDUCER_ID, } from '~/routes/safe/store/reducer/transactions' -export const history = createBrowserHistory() +export const history = process.env.NODE_ENV === 'test' ? createMemoryHistory() : createBrowserHistory() // eslint-disable-next-line const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose @@ -29,15 +29,14 @@ export type GlobalState = { export type GetState = () => GlobalState -// customHistory is passed in tests, check test/builder/safe.dom.utils.js -const reducers: Reducer = (customHistory: any = history) => combineReducers({ - router: connectRouter(customHistory), +const reducers: Reducer = combineReducers({ + router: connectRouter(history), [PROVIDER_REDUCER_ID]: provider, [SAFE_REDUCER_ID]: safe, [TOKEN_REDUCER_ID]: tokens, [TRANSACTIONS_REDUCER_ID]: transactions, }) -export const store: Store = createStore(reducers(), finalCreateStore) +export const store: Store = createStore(reducers, finalCreateStore) -export const aNewStore = (localState?: Object, customHistory: any = history): Store => createStore(reducers(customHistory), localState, finalCreateStore) +export const aNewStore = (localState?: Object): Store => createStore(reducers, localState, finalCreateStore) diff --git a/src/test/builder/safe.dom.utils.js b/src/test/builder/safe.dom.utils.js index f8b8095f..7f5315f9 100644 --- a/src/test/builder/safe.dom.utils.js +++ b/src/test/builder/safe.dom.utils.js @@ -1,21 +1,20 @@ // @flow import * as React from 'react' import TestUtils from 'react-dom/test-utils' -import { createMemoryHistory } from 'history' +import { type Store } from 'redux' +import { Provider } from 'react-redux' +import { ConnectedRouter } from 'connected-react-router' +import PageFrame from '~/components/layout/PageFrame' import { render } from '@testing-library/react' import ListItemText from '~/components/List/ListItemText/index' import { SEE_MULTISIG_BUTTON_TEXT } from '~/routes/safe/components/Safe/MultisigTx' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import { sleep } from '~/utils/timer' -import { aNewStore, type GlobalState } from '~/store' -import { Provider } from 'react-redux' -import { ConnectedRouter } from 'connected-react-router' +import { history } from '~/store' import AppRoutes from '~/routes' import { SAFELIST_ADDRESS, SETTINS_ADDRESS } from '~/routes/routes' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' -export const testHistory = createMemoryHistory - export const EXPAND_BALANCE_INDEX = 0 export const EXPAND_OWNERS_INDEX = 1 export const ADD_OWNERS_INDEX = 2 @@ -100,35 +99,33 @@ const renderApp = (store: Store) => ({ ...render( - }> - - + + }> + + + , ), - store, + history, }) -export const renderSafeView = (address: string) => { +export const renderSafeView = (store: Store, address: string) => { + const app = renderApp(store) + const url = `${SAFELIST_ADDRESS}/${address}` - const history = createMemoryHistory({ initialEntries: [url] }) - const store = aNewStore(history) + history.push(url) - return renderApp(store, history) + return app } -export const travelToTokens = (address: string) => { +export const travelToTokens = (store: Store, address: string) => { + const app = renderApp(store) + const url = `${SAFELIST_ADDRESS}/${address}${SETTINS_ADDRESS}` - const history = createMemoryHistory({ initialEntries: [url] }) - const store = aNewStore(history) + history.push(url) - return renderApp(store, history) -} - -export const createTestStore = (initialRoute = '/') => { - const history = createMemoryHistory({ initialEntries: [initialRoute] }) - - return aNewStore(history) + return app } const INTERVAL = 500 diff --git a/src/test/safe.dom.funds.test.js b/src/test/safe.dom.funds.test.js index 411d96d1..d8806e25 100644 --- a/src/test/safe.dom.funds.test.js +++ b/src/test/safe.dom.funds.test.js @@ -1,54 +1,67 @@ // @flow -import { render, fireEvent, cleanup } from '@testing-library/react' -import * as fetchBalancesAction from '~/logic/tokens/store/actions/fetchTokens' +import { fireEvent, cleanup } from '@testing-library/react' +import { aNewStore } from '~/store' import { aMinedSafe } from '~/test/builder/safe.redux.builder' -import { sendTokenTo, getFirstTokenContract } from '~/test/utils/tokenMovements' -import { EXPAND_BALANCE_INDEX, renderSafeView, createTestStore } from '~/test/builder/safe.dom.utils' -import { getWeb3 } from '~/logic/wallets/getWeb3' +import { sendTokenTo, getFirstTokenContract, sendEtherTo } from '~/test/utils/tokenMovements' +import { EXPAND_BALANCE_INDEX, renderSafeView } from '~/test/builder/safe.dom.utils' +import { getWeb3, getBalanceInEtherOf } from '~/logic/wallets/getWeb3' import { sendMoveTokensForm, dispatchTknBalance } from '~/test/utils/transactions/moveTokens.helper' import { sleep } from '~/utils/timer' +import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' +import { calculateBalanceOf } from '~/routes/safe/store/actions/fetchTokenBalances' +import 'jest-dom/extend-expect' afterEach(cleanup) describe('DOM > Feature > Funds', () => { + let store let safeAddress: string let accounts beforeEach(async () => { + store = aNewStore() safeAddress = await aMinedSafe(store) accounts = await getWeb3().eth.getAccounts() }) it('Sends ETH', async () => { // GIVEN - const numTokens = '100' - const tokenAddress = await sendTokenTo(safeAddress, numTokens) - const SafeDom = await renderSafeView(safeAddress) - const { store } = SafeDom - - await dispatchTknBalance(store, tokenAddress, safeAddress) - // const StandardToken = await fetchBalancesAction.getStandardTokenContract() - // const myToken = await StandardToken.at(tokenAddress) - // console.log(await myToken.allowance(safeAddress, accounts[2])) - // console.log(await myToken.balanceOf(safeAddress)) + const ethAmount = '5' + await sendEtherTo(safeAddress, ethAmount) + const balanceAfterSendingEthToSafe = await getBalanceInEtherOf(accounts[0]) // WHEN - await sleep(1500) - console.log(SafeDom.history) + const SafeDom = renderSafeView(store, safeAddress) + await sleep(1000) + + // Open send funds modal const balanceRows = SafeDom.getAllByTestId('balance-row') - const buttons = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'button') - const expandBalance = buttons[EXPAND_BALANCE_INDEX] - const receiver = accounts[2] - await sendMoveTokensForm(SafeDom, expandBalance, 20, accounts[2]) + expect(balanceRows[0]).toHaveTextContent(`${ethAmount} ETH`) + const sendButton = SafeDom.getByTestId('balance-send-btn') + fireEvent.click(sendButton) + + // Fill first send funds screen + const recipientInput = SafeDom.getByPlaceholderText('Recipient*') + const amountInput = SafeDom.getByPlaceholderText('Amount*') + const reviewBtn = SafeDom.getByTestId('review-tx-btn') + fireEvent.change(recipientInput, { target: { value: accounts[0] } }) + fireEvent.change(amountInput, { target: { value: ethAmount } }) + await sleep(200) + fireEvent.click(reviewBtn) + + // Submit the tx (Review Tx screen) + const submitBtn = SafeDom.getByTestId('submit-tx-btn') + fireEvent.click(submitBtn) + await sleep(1000) // THEN - const safeFunds = await fetchBalancesAction.calculateBalanceOf(tokenAddress, safeAddress, 18) - expect(Number(safeFunds)).toBe(80) - const receiverFunds = await fetchBalancesAction.calculateBalanceOf(tokenAddress, receiver, 18) - expect(Number(receiverFunds)).toBe(20) + const safeFunds = await calculateBalanceOf(ETH_ADDRESS, safeAddress, 18) + expect(Number(safeFunds)).toBe(0) - const token = await getFirstTokenContract(getWeb3(), accounts[0]) - const nativeSafeFunds = await token.balanceOf(safeAddress) - expect(Number(nativeSafeFunds.valueOf())).toEqual(80 * 10 ** 18) + const receiverFunds = await getBalanceInEtherOf(accounts[0]) + const ESTIMATED_GASCOSTS = 0.1 + expect(Number(parseInt(receiverFunds, 10) - parseInt(balanceAfterSendingEthToSafe, 10))).toBeGreaterThan( + parseInt(ethAmount, 10) - ESTIMATED_GASCOSTS, + ) }) it('Sends Tokens', async () => { diff --git a/src/test/safe.dom.tokens.test.js b/src/test/safe.dom.tokens.test.js new file mode 100644 index 00000000..fe5e856c --- /dev/null +++ b/src/test/safe.dom.tokens.test.js @@ -0,0 +1,73 @@ +// @flow + +import TestUtils from 'react-dom/test-utils' +import * as fetchBalancesAction from '~/logic/tokens/store/actions/fetchTokens' +import { aNewStore } from '~/store' +import { aMinedSafe } from '~/test/builder/safe.redux.builder' +import { addTknTo, getFirstTokenContract } from '~/test/utils/tokenMovements' +import { EXPAND_BALANCE_INDEX, travelToSafe } from '~/test/builder/safe.dom.utils' +import { getWeb3 } from '~/logic/wallets/getWeb3' +import { sendMoveTokensForm, dispatchTknBalance } from '~/test/utils/transactions/moveTokens.helper' +import { sleep } from '~/utils/timer' + +describe('DOM > Feature > SAFE ERC20 TOKENS', () => { + let accounts + beforeEach(async () => { + accounts = await getWeb3().eth.getAccounts() + }) + + it('sends ERC20 tokens', async () => { + // GIVEN + const store = aNewStore() + const safeAddress = await aMinedSafe(store) + + const numTokens = '100' + const tokenAddress = await addTknTo(safeAddress, numTokens) + + await dispatchTknBalance(store, tokenAddress, safeAddress) + // const StandardToken = await fetchBalancesAction.getStandardTokenContract() + // const myToken = await StandardToken.at(tokenAddress) + // console.log(await myToken.allowance(safeAddress, accounts[2])) + // console.log(await myToken.balanceOf(safeAddress)) + + // WHEN + const SafeDom = await travelToSafe(store, safeAddress) + await sleep(800) + // $FlowFixMe + const buttons = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'button') + const expandBalance = buttons[EXPAND_BALANCE_INDEX] + const receiver = accounts[2] + await sendMoveTokensForm(SafeDom, expandBalance, 20, accounts[2]) + + // THEN + const safeFunds = await fetchBalancesAction.calculateBalanceOf(tokenAddress, safeAddress, 18) + expect(Number(safeFunds)).toBe(80) + const receiverFunds = await fetchBalancesAction.calculateBalanceOf(tokenAddress, receiver, 18) + expect(Number(receiverFunds)).toBe(20) + + const token = await getFirstTokenContract(getWeb3(), accounts[0]) + const nativeSafeFunds = await token.balanceOf(safeAddress) + expect(Number(nativeSafeFunds.valueOf())).toEqual(80 * 10 ** 18) + }) + + it('disables send token button when balance is 0', async () => { + // GIVEN + const token = await getFirstTokenContract(getWeb3(), accounts[0]) + await dispatchTknBalance(store, token.address, safeAddress) + + // WHEN + const SafeDom = travelToSafe(store, safeAddress) + + // $FlowFixMe + const buttons = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'button') + const expandBalance = buttons[EXPAND_BALANCE_INDEX] + + TestUtils.Simulate.click(expandBalance) + await sleep(800) + + // $FlowFixMe + const balanceButtons = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'button') + const tokenButton = balanceButtons[EXPAND_BALANCE_INDEX + 1] // expand button, and the next one is for sending + expect(tokenButton.hasAttribute('disabled')).toBe(true) + }) +}) diff --git a/src/test/utils/tokenMovements.js b/src/test/utils/tokenMovements.js index 5cf9179b..60cbaec5 100644 --- a/src/test/utils/tokenMovements.js +++ b/src/test/utils/tokenMovements.js @@ -9,7 +9,8 @@ import TokenRDN from '../../../build/contracts/TokenRDN' export const sendEtherTo = async (address: string, eth: string) => { const web3 = getWeb3() const accounts = await web3.eth.getAccounts() - const txData = { from: accounts[0], to: address, value: web3.utils.toWei(eth, 'ether') } + const { toBN, toWei } = web3.utils + const txData = { from: accounts[0], to: address, value: toBN(toWei(eth, 'ether')) } return web3.eth.sendTransaction(txData) } @@ -21,7 +22,9 @@ export const checkBalanceOf = async (addressToTest: string, value: string) => { const createTokenOMGContract = async (web3: any, creator: string) => { const token = contract(TokenOMG) const { toBN } = web3.utils - const amount = toBN(50000).mul(toBN(10).pow(toBN(18))).toString() + const amount = toBN(50000) + .mul(toBN(10).pow(toBN(18))) + .toString() token.setProvider(web3.currentProvider) return token.new(amount, { from: creator }) @@ -30,7 +33,9 @@ const createTokenOMGContract = async (web3: any, creator: string) => { const createTokenRDNContract = async (web3: any, creator: string) => { const token = contract(TokenRDN) const { toBN } = web3.utils - const amount = toBN(50000).mul(toBN(10).pow(toBN(18))).toString() + const amount = toBN(50000) + .mul(toBN(10).pow(toBN(18))) + .toString() token.setProvider(web3.currentProvider) return token.new(amount, { from: creator }) diff --git a/yarn.lock b/yarn.lock index 008a7126..49f26f14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1282,12 +1282,6 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.2.tgz#63985d3d8b02530e0869962f4da09142ee8e200e" integrity sha512-n/VQ4mbfr81aqkx/XmVicOLjviMuy02eenSdJY33SVA7S2J42EU0P1H0mOogfYedb3wXA0d/LVtBrgTSm04WEA== -"@gnosis.pm/mock-contract@github:gnosis/mock-contract#sol_0_5_0": - version "2.0.2" - resolved "https://codeload.github.com/gnosis/mock-contract/tar.gz/2ec1266eeef1baf7514cdb65b3a3a1aef224f3f2" - dependencies: - ethereumjs-abi "^0.6.5" - "@gnosis.pm/safe-contracts@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.0.0.tgz#2b562b1e23a0da1047a9f38ef71a70f811e75dd9" @@ -5558,6 +5552,21 @@ css-what@2.1, css-what@^2.1.2: resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= + +css@^2.2.3: + version "2.2.4" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" + integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== + dependencies: + inherits "^2.0.3" + source-map "^0.6.1" + source-map-resolve "^0.5.2" + urix "^0.1.0" + cssesc@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" @@ -6869,7 +6878,7 @@ ethereumjs-abi@0.6.5: bn.js "^4.10.0" ethereumjs-util "^4.3.0" -ethereumjs-abi@^0.6.5, ethereumjs-abi@^0.6.7, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": +ethereumjs-abi@^0.6.7, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": version "0.6.7" resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#8431eab7b3384e65e8126a4602520b78031666fb" dependencies: @@ -7252,7 +7261,7 @@ expect@^24.8.0: jest-message-util "^24.8.0" jest-regex-util "^24.3.0" -express@^4.14.0, express@^4.16.3, express@^4.17.0: +express@^4.14.0, express@^4.16.3, express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== @@ -7574,10 +7583,10 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -final-form@4.13.0: - version "4.13.0" - resolved "https://registry.yarnpkg.com/final-form/-/final-form-4.13.0.tgz#ef2b36a850d6287cd968f328180590e5a64a57bb" - integrity sha512-JD/MPstXejGtQOryhbLHJoOtsvcCV37baoVuwK/+/mgbNir3QZjedhUJoSqgjwMxk/H1j/usdDwy7xfKMAq/dw== +final-form@4.13.1: + version "4.13.1" + resolved "https://registry.yarnpkg.com/final-form/-/final-form-4.13.1.tgz#5893b1fe490a36198b219b351eec135d7394cdcf" + integrity sha512-9bTIY68bKn6rIcyolFZlUqK1odlRXpi30C5CazJ5gUZpoMkeDAeb53FQ3gv37eX1zWtQtydgwD5ZAwZB5EGoGg== dependencies: "@babel/runtime" "^7.3.1" @@ -7664,10 +7673,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== -flow-bin@0.99.1: - version "0.99.1" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.99.1.tgz#0d4f413ca84a3a95d0aa64214178684dd7c6a4c5" - integrity sha512-dipNwJlb4MsVt3IuDgPTymCNL4GFoq3pG+GbY6DmBbl0dJPWFSA383rCTmgbfFhoeJ1XCfYBan0BPryToSxiiQ== +flow-bin@0.100.0: + version "0.100.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.100.0.tgz#729902726658cfa0a81425d6401f9625cf9f5534" + integrity sha512-jcethhgrslBJukH7Z7883ohFFpzLrdsOEwHxvn5NwuTWbNaE71GAl55/PEBRJwYpDvYkRlqgcNkANTv0x5XjqA== flush-write-stream@^1.0.0: version "1.1.1" @@ -8913,7 +8922,7 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -indent-string@^3.1.0, indent-string@^3.2.0: +indent-string@^3.0.0, indent-string@^3.1.0, indent-string@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= @@ -9607,7 +9616,7 @@ jest-config@^24.8.0: pretty-format "^24.8.0" realpath-native "^1.1.0" -jest-diff@^24.8.0: +jest-diff@^24.0.0, jest-diff@^24.8.0: version "24.8.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172" integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g== @@ -9624,6 +9633,20 @@ jest-docblock@^24.3.0: dependencies: detect-newline "^2.1.0" +jest-dom@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/jest-dom/-/jest-dom-3.4.0.tgz#46c21984a73a4841dc57bc8fc09ccd1d971a8447" + integrity sha512-fQR5ESaxTfNbZE02y+gtaQH7+sMwzrQtJo5OE0E3BNArjTL9GWNI+uPFr1yS24eodH1X62L+qncv106M/O98gQ== + dependencies: + chalk "^2.4.1" + css "^2.2.3" + css.escape "^1.5.1" + jest-diff "^24.0.0" + jest-matcher-utils "^24.0.0" + lodash "^4.17.11" + pretty-format "^24.0.0" + redent "^2.0.0" + jest-each@^24.8.0: version "24.8.0" resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.8.0.tgz#a05fd2bf94ddc0b1da66c6d13ec2457f35e52775" @@ -9711,7 +9734,7 @@ jest-leak-detector@^24.8.0: dependencies: pretty-format "^24.8.0" -jest-matcher-utils@^24.8.0: +jest-matcher-utils@^24.0.0, jest-matcher-utils@^24.8.0: version "24.8.0" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz#2bce42204c9af12bde46f83dc839efe8be832495" integrity sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw== @@ -10697,7 +10720,7 @@ loglevel-colored-level-prefix@^1.0.0: chalk "^1.1.3" loglevel "^1.4.1" -loglevel@^1.4.1, loglevel@^1.6.1: +loglevel@^1.4.1, loglevel@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.2.tgz#668c77948a03dbd22502a3513ace1f62a80cc372" integrity sha512-Jt2MHrCNdtIe1W6co3tF5KXGRkzF+TYffiQstfXa04mrss9IKXzAAXYWak8LbZseAQY03sH2GzMCMU0ZOUc9bg== @@ -12795,7 +12818,7 @@ pretty-format@^23.0.1: ansi-regex "^3.0.0" ansi-styles "^3.2.0" -pretty-format@^24.8.0: +pretty-format@^24.0.0, pretty-format@^24.8.0: version "24.8.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2" integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw== @@ -13321,10 +13344,10 @@ react-helmet-async@^0.2.0: react-fast-compare "^2.0.2" shallowequal "^1.0.2" -react-hot-loader@4.8.8: - version "4.8.8" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.8.8.tgz#71e3c7ba301556aa24c52cef2f6ed0af82395eea" - integrity sha512-58bgeS7So8V93MhhnKogbraor8xdrTncil+b6IoIXkTIr3blJNAE7bU4tn/iJvy2J7rjxQmKFRaxKrWdKUZpqg== +react-hot-loader@4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.9.0.tgz#498e5f76aae28bfd420efdabddf5af156745b4dd" + integrity sha512-1N6MWV9++qYWrrs41MRhxATwyx743tr8RpeyL1VOZ54zsU8fOx4slYreHZ8v2BDGVfy+dJ0myJZrJA9/26RlCA== dependencies: fast-levenshtein "^2.0.6" global "^4.3.0" @@ -13700,6 +13723,14 @@ recursive-readdir@2.2.2: dependencies: minimatch "3.0.4" +redent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= + dependencies: + indent-string "^3.0.0" + strip-indent "^2.0.0" + reduce-reducers@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-0.4.3.tgz#8e052618801cd8fc2714b4915adaa8937eb6d66c" @@ -14498,7 +14529,7 @@ semver@5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@^6.0.0, semver@^6.1.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.1.tgz#53f53da9b30b2103cd4f15eab3a18ecbcb210c9b" integrity sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ== @@ -14858,7 +14889,7 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-resolve@^0.5.0: +source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== @@ -15258,6 +15289,11 @@ strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed "1.0.0" +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= + strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -17722,10 +17758,10 @@ webpack-dev-middleware@^3.5.1, webpack-dev-middleware@^3.7.0: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.4.1.tgz#a5fd8dec95dec410098e7d9a037ff9405395d51a" - integrity sha512-CRqZQX2ryMtrg0r3TXQPpNh76eM1HD3Wmu6zDBxIKi/d2y+4aa28Ia8weNT0bfgWpY6Vs3Oq/K8+DjfbR+tWYw== +webpack-dev-server@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.5.1.tgz#4290ac709bb989dc7382c912899f79fd5677dabf" + integrity sha512-0IdMGddJcnK9zesZOeHWl4uAOVfypn7DSrdNWtclROkVBXy/TcBN+6eEG1wNfLT9dXVfaRZZsLTJt0mJtgTQgw== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -17734,19 +17770,19 @@ webpack-dev-server@3.4.1: connect-history-api-fallback "^1.6.0" debug "^4.1.1" del "^4.1.1" - express "^4.17.0" + express "^4.17.1" html-entities "^1.2.1" http-proxy-middleware "^0.19.1" import-local "^2.0.0" internal-ip "^4.3.0" ip "^1.1.5" killable "^1.0.1" - loglevel "^1.6.1" + loglevel "^1.6.2" opn "^5.5.0" portfinder "^1.0.20" schema-utils "^1.0.0" selfsigned "^1.10.4" - semver "^6.0.0" + semver "^6.1.1" serve-index "^1.9.1" sockjs "0.3.19" sockjs-client "1.3.0"