Merge pull request #131 from gnosis/send-funds-multiple-owners-tests
TESTS: Sending funds for multiple owners/Tx list
This commit is contained in:
commit
462cb47a88
|
@ -23,7 +23,6 @@
|
||||||
"start": "node scripts/start.js",
|
"start": "node scripts/start.js",
|
||||||
"storybook": "start-storybook -p 6006",
|
"storybook": "start-storybook -p 6006",
|
||||||
"test": "NODE_ENV=test && node scripts/test.js --env=jsdom",
|
"test": "NODE_ENV=test && node scripts/test.js --env=jsdom",
|
||||||
"test-local": "NODE_ENV=test && node scripts/test.js --env=jsdom",
|
|
||||||
"format": "prettier-eslint \"src/**/*.js\" --write"
|
"format": "prettier-eslint \"src/**/*.js\" --write"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
"pre-commit": [
|
||||||
|
@ -54,7 +53,7 @@
|
||||||
"react-hot-loader": "4.12.7",
|
"react-hot-loader": "4.12.7",
|
||||||
"react-infinite-scroll-component": "^4.5.2",
|
"react-infinite-scroll-component": "^4.5.2",
|
||||||
"react-redux": "7.1.0",
|
"react-redux": "7.1.0",
|
||||||
"react-router-dom": "^4.3.1",
|
"react-router-dom": "^5.0.1",
|
||||||
"recompose": "^0.30.0",
|
"recompose": "^0.30.0",
|
||||||
"redux": "4.0.4",
|
"redux": "4.0.4",
|
||||||
"redux-actions": "^2.3.0",
|
"redux-actions": "^2.3.0",
|
||||||
|
@ -104,7 +103,7 @@
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"css-loader": "3.0.0",
|
"css-loader": "3.0.0",
|
||||||
"detect-port": "^1.2.2",
|
"detect-port": "^1.2.2",
|
||||||
"eslint": "6.0.1",
|
"eslint": "5.16.0",
|
||||||
"eslint-config-airbnb": "17.1.1",
|
"eslint-config-airbnb": "17.1.1",
|
||||||
"eslint-plugin-flowtype": "3.11.1",
|
"eslint-plugin-flowtype": "3.11.1",
|
||||||
"eslint-plugin-import": "2.18.0",
|
"eslint-plugin-import": "2.18.0",
|
||||||
|
|
17
readme.md
17
readme.md
|
@ -35,22 +35,29 @@ yarn start
|
||||||
|
|
||||||
## Running the tests
|
## Running the tests
|
||||||
|
|
||||||
To run the test, you'll need to migrate contracts `safe-contracts` to the local ganache-cli
|
1. Run `transaction-history-service`
|
||||||
|
```
|
||||||
|
git clone https://github.com/gnosis/safe-transaction-service.git
|
||||||
|
cd safe-transaction-history
|
||||||
|
git checkout develop
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
Check that the service is running at https://localhost:8000
|
||||||
|
|
||||||
1. Migrating Safe Contracts:
|
2. Migrate Safe Contracts:
|
||||||
```
|
```
|
||||||
git clone https://github.com/gnosis/safe-contracts.git
|
git clone https://github.com/gnosis/safe-contracts.git
|
||||||
cd safe-contracts
|
cd safe-contracts
|
||||||
yarn
|
yarn
|
||||||
ganache-cli -l 7000000
|
|
||||||
npx truffle migrate
|
npx truffle migrate
|
||||||
```
|
```
|
||||||
2. Migrate Token Contracts for the tests:
|
3. Migrate Token Contracts for the tests:
|
||||||
Inside `safe-react` directory
|
Inside `safe-react` directory
|
||||||
```
|
```
|
||||||
npx truffle migrate
|
npx truffle migrate
|
||||||
```
|
```
|
||||||
3. Run the tests:
|
4. Run the tests:
|
||||||
```
|
```
|
||||||
yarn test
|
yarn test
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
TX_SERVICE_HOST,
|
TX_SERVICE_HOST,
|
||||||
ENABLED_TX_SERVICE_REMOVAL_SENDER,
|
|
||||||
SIGNATURES_VIA_METAMASK,
|
SIGNATURES_VIA_METAMASK,
|
||||||
RELAY_API_URL,
|
RELAY_API_URL,
|
||||||
} from '~/config/names'
|
} from '~/config/names'
|
||||||
|
|
||||||
const devConfig = {
|
const devConfig = {
|
||||||
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
||||||
[ENABLED_TX_SERVICE_REMOVAL_SENDER]: false,
|
|
||||||
[SIGNATURES_VIA_METAMASK]: false,
|
[SIGNATURES_VIA_METAMASK]: false,
|
||||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import { ensureOnce } from '~/utils/singleton'
|
import { ensureOnce } from '~/utils/singleton'
|
||||||
import {
|
import {
|
||||||
TX_SERVICE_HOST,
|
TX_SERVICE_HOST,
|
||||||
ENABLED_TX_SERVICE_REMOVAL_SENDER,
|
|
||||||
SIGNATURES_VIA_METAMASK,
|
SIGNATURES_VIA_METAMASK,
|
||||||
RELAY_API_URL,
|
RELAY_API_URL,
|
||||||
} from '~/config/names'
|
} from '~/config/names'
|
||||||
|
@ -34,12 +33,6 @@ export const getTxServiceUriFrom = (safeAddress: string) => `safes/${safeAddress
|
||||||
|
|
||||||
export const getRelayUrl = () => getConfig()[RELAY_API_URL]
|
export const getRelayUrl = () => getConfig()[RELAY_API_URL]
|
||||||
|
|
||||||
export const allowedRemoveSenderInTxHistoryService = () => {
|
|
||||||
const config = getConfig()
|
|
||||||
|
|
||||||
return config[ENABLED_TX_SERVICE_REMOVAL_SENDER]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const signaturesViaMetamask = () => {
|
export const signaturesViaMetamask = () => {
|
||||||
const config = getConfig()
|
const config = getConfig()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
export const TX_SERVICE_HOST = 'tsh'
|
export const TX_SERVICE_HOST = 'tsh'
|
||||||
export const ENABLED_TX_SERVICE_REMOVAL_SENDER = 'trs'
|
|
||||||
export const SIGNATURES_VIA_METAMASK = 'svm'
|
export const SIGNATURES_VIA_METAMASK = 'svm'
|
||||||
export const RELAY_API_URL = 'rau'
|
export const RELAY_API_URL = 'rau'
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
TX_SERVICE_HOST,
|
TX_SERVICE_HOST,
|
||||||
ENABLED_TX_SERVICE_REMOVAL_SENDER,
|
|
||||||
SIGNATURES_VIA_METAMASK,
|
SIGNATURES_VIA_METAMASK,
|
||||||
RELAY_API_URL,
|
RELAY_API_URL,
|
||||||
} from '~/config/names'
|
} from '~/config/names'
|
||||||
|
|
||||||
const prodConfig = {
|
const prodConfig = {
|
||||||
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
||||||
[ENABLED_TX_SERVICE_REMOVAL_SENDER]: false,
|
|
||||||
[SIGNATURES_VIA_METAMASK]: false,
|
[SIGNATURES_VIA_METAMASK]: false,
|
||||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import {
|
import {
|
||||||
TX_SERVICE_HOST,
|
TX_SERVICE_HOST,
|
||||||
ENABLED_TX_SERVICE_REMOVAL_SENDER,
|
|
||||||
SIGNATURES_VIA_METAMASK,
|
SIGNATURES_VIA_METAMASK,
|
||||||
RELAY_API_URL,
|
RELAY_API_URL,
|
||||||
} from '~/config/names'
|
} from '~/config/names'
|
||||||
|
|
||||||
const testConfig = {
|
const testConfig = {
|
||||||
[TX_SERVICE_HOST]: 'https://safe-transaction-service.dev.gnosisdev.com/api/v1/',
|
[TX_SERVICE_HOST]: 'http://localhost:8000/api/v1/',
|
||||||
[ENABLED_TX_SERVICE_REMOVAL_SENDER]: false,
|
|
||||||
[SIGNATURES_VIA_METAMASK]: false,
|
[SIGNATURES_VIA_METAMASK]: false,
|
||||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1',
|
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1',
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,19 +39,17 @@ export const approveTransaction = async (
|
||||||
)
|
)
|
||||||
const receipt = await safeInstance.approveHash(contractTxHash, { from: sender })
|
const receipt = await safeInstance.approveHash(contractTxHash, { from: sender })
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'test') {
|
await saveTxToHistory(
|
||||||
await saveTxToHistory(
|
safeInstance,
|
||||||
safeInstance,
|
to,
|
||||||
to,
|
valueInWei,
|
||||||
valueInWei,
|
data,
|
||||||
data,
|
operation,
|
||||||
operation,
|
nonce,
|
||||||
nonce,
|
receipt.tx, // tx hash,
|
||||||
receipt.tx, // tx hash,
|
sender,
|
||||||
sender,
|
TX_TYPE_CONFIRMATION,
|
||||||
TX_TYPE_CONFIRMATION,
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return receipt
|
return receipt
|
||||||
}
|
}
|
||||||
|
@ -91,19 +89,17 @@ export const executeTransaction = async (
|
||||||
{ from: sender },
|
{ from: sender },
|
||||||
)
|
)
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'test') {
|
await saveTxToHistory(
|
||||||
await saveTxToHistory(
|
safeInstance,
|
||||||
safeInstance,
|
to,
|
||||||
to,
|
valueInWei,
|
||||||
valueInWei,
|
data,
|
||||||
data,
|
operation,
|
||||||
operation,
|
nonce,
|
||||||
nonce,
|
receipt.tx, // tx hash,
|
||||||
receipt.tx, // tx hash,
|
sender,
|
||||||
sender,
|
TX_TYPE_EXECUTION,
|
||||||
TX_TYPE_EXECUTION,
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return receipt
|
return receipt
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -57,6 +57,10 @@ const getProviderName: Function = (web3Provider): boolean => {
|
||||||
const getAccountFrom: Function = async (web3Provider): Promise<string | null> => {
|
const getAccountFrom: Function = async (web3Provider): Promise<string | null> => {
|
||||||
const accounts = await web3Provider.eth.getAccounts()
|
const accounts = await web3Provider.eth.getAccounts()
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'test' && window.testAccountIndex) {
|
||||||
|
return accounts[window.testAccountIndex]
|
||||||
|
}
|
||||||
|
|
||||||
return accounts && accounts.length > 0 ? accounts[0] : null
|
return accounts && accounts.length > 0 ? accounts[0] : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,10 @@ import Balances from './Balances'
|
||||||
import Transactions from './TransactionsNew'
|
import Transactions from './TransactionsNew'
|
||||||
import Settings from './Settings'
|
import Settings from './Settings'
|
||||||
|
|
||||||
export const SETTINGS_TAB_BTN_TESTID = 'settings-tab-btn'
|
export const BALANCES_TAB_BTN_TEST_ID = 'balances-tab-btn'
|
||||||
export const SAFE_VIEW_NAME_HEADING_TESTID = 'safe-name-heading'
|
export const SETTINGS_TAB_BTN_TEST_ID = 'settings-tab-btn'
|
||||||
|
export const TRANSACTIONS_TAB_BTN_TEST_ID = 'transactions-tab-btn'
|
||||||
|
export const SAFE_VIEW_NAME_HEADING_TEST_ID = 'safe-name-heading'
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
tabIndex: number,
|
tabIndex: number,
|
||||||
|
@ -126,7 +128,7 @@ class Layout extends React.Component<Props, State> {
|
||||||
<Identicon address={address} diameter={50} />
|
<Identicon address={address} diameter={50} />
|
||||||
<Block className={classes.name}>
|
<Block className={classes.name}>
|
||||||
<Row>
|
<Row>
|
||||||
<Heading tag="h2" color="secondary" testId={SAFE_VIEW_NAME_HEADING_TESTID}>
|
<Heading tag="h2" color="secondary" testId={SAFE_VIEW_NAME_HEADING_TEST_ID}>
|
||||||
{name}
|
{name}
|
||||||
</Heading>
|
</Heading>
|
||||||
{!granted && <Block className={classes.readonly}>Read Only</Block>}
|
{!granted && <Block className={classes.readonly}>Read Only</Block>}
|
||||||
|
@ -143,9 +145,9 @@ class Layout extends React.Component<Props, State> {
|
||||||
</Block>
|
</Block>
|
||||||
<Row>
|
<Row>
|
||||||
<Tabs value={tabIndex} onChange={this.handleChange} indicatorColor="secondary" textColor="secondary">
|
<Tabs value={tabIndex} onChange={this.handleChange} indicatorColor="secondary" textColor="secondary">
|
||||||
<Tab label="Balances" />
|
<Tab label="Balances" data-testid={BALANCES_TAB_BTN_TEST_ID} />
|
||||||
<Tab label="Transactions" />
|
<Tab label="Transactions" data-testid={TRANSACTIONS_TAB_BTN_TEST_ID} />
|
||||||
<Tab label="Settings" data-testid={SETTINGS_TAB_BTN_TESTID} />
|
<Tab label="Settings" data-testid={SETTINGS_TAB_BTN_TEST_ID} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Row>
|
</Row>
|
||||||
<Hairline color="#c8ced4" />
|
<Hairline color="#c8ced4" />
|
||||||
|
|
|
@ -20,8 +20,8 @@ const controlsStyle = {
|
||||||
padding: sm,
|
padding: sm,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SAFE_NAME_INPUT_TESTID = 'safe-name-input'
|
export const SAFE_NAME_INPUT_TEST_ID = 'safe-name-input'
|
||||||
export const SAFE_NAME_SUBMIT_BTN_TESTID = 'change-safe-name-btn'
|
export const SAFE_NAME_SUBMIT_BTN_TEST_ID = 'change-safe-name-btn'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
classes: Object,
|
classes: Object,
|
||||||
|
@ -59,7 +59,7 @@ const ChangeSafeName = (props: Props) => {
|
||||||
placeholder="Safe name*"
|
placeholder="Safe name*"
|
||||||
text="Safe name*"
|
text="Safe name*"
|
||||||
defaultValue={safeName}
|
defaultValue={safeName}
|
||||||
testId={SAFE_NAME_INPUT_TESTID}
|
testId={SAFE_NAME_INPUT_TEST_ID}
|
||||||
/>
|
/>
|
||||||
</Block>
|
</Block>
|
||||||
</Block>
|
</Block>
|
||||||
|
@ -72,7 +72,7 @@ const ChangeSafeName = (props: Props) => {
|
||||||
size="small"
|
size="small"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
testId={SAFE_NAME_SUBMIT_BTN_TESTID}
|
testId={SAFE_NAME_SUBMIT_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
SAVE
|
SAVE
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -23,9 +23,9 @@ import {
|
||||||
} from '~/components/forms/validator'
|
} from '~/components/forms/validator'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
export const ADD_OWNER_NAME_INPUT_TESTID = 'add-owner-name-input'
|
export const ADD_OWNER_NAME_INPUT_TEST_ID = 'add-owner-name-input'
|
||||||
export const ADD_OWNER_ADDRESS_INPUT_TESTID = 'add-owner-address-testid'
|
export const ADD_OWNER_ADDRESS_INPUT_TEST_ID = 'add-owner-address-testid'
|
||||||
export const ADD_OWNER_NEXT_BTN_TESTID = 'add-owner-next-btn'
|
export const ADD_OWNER_NEXT_BTN_TEST_ID = 'add-owner-next-btn'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
|
@ -71,7 +71,7 @@ const OwnerForm = ({
|
||||||
placeholder="Owner name*"
|
placeholder="Owner name*"
|
||||||
text="Owner name*"
|
text="Owner name*"
|
||||||
className={classes.addressInput}
|
className={classes.addressInput}
|
||||||
testId={ADD_OWNER_NAME_INPUT_TESTID}
|
testId={ADD_OWNER_NAME_INPUT_TEST_ID}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -85,7 +85,7 @@ const OwnerForm = ({
|
||||||
placeholder="Owner address*"
|
placeholder="Owner address*"
|
||||||
text="Owner address*"
|
text="Owner address*"
|
||||||
className={classes.addressInput}
|
className={classes.addressInput}
|
||||||
testId={ADD_OWNER_ADDRESS_INPUT_TESTID}
|
testId={ADD_OWNER_ADDRESS_INPUT_TEST_ID}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -101,7 +101,7 @@ const OwnerForm = ({
|
||||||
variant="contained"
|
variant="contained"
|
||||||
minWidth={140}
|
minWidth={140}
|
||||||
color="primary"
|
color="primary"
|
||||||
testId={ADD_OWNER_NEXT_BTN_TESTID}
|
testId={ADD_OWNER_NEXT_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
Next
|
Next
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary } from '~/theme/variables'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
export const ADD_OWNER_SUBMIT_BTN_TESTID = 'add-owner-submit-btn'
|
export const ADD_OWNER_SUBMIT_BTN_TEST_ID = 'add-owner-submit-btn'
|
||||||
|
|
||||||
const openIconStyle = {
|
const openIconStyle = {
|
||||||
height: '16px',
|
height: '16px',
|
||||||
|
@ -164,7 +164,7 @@ const ReviewAddOwner = ({
|
||||||
variant="contained"
|
variant="contained"
|
||||||
minWidth={140}
|
minWidth={140}
|
||||||
color="primary"
|
color="primary"
|
||||||
testId={ADD_OWNER_SUBMIT_BTN_TESTID}
|
testId={ADD_OWNER_SUBMIT_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
} from '~/components/forms/validator'
|
} from '~/components/forms/validator'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
export const ADD_OWNER_THRESHOLD_NEXT_BTN_TESTID = 'add-owner-threshold-next-btn'
|
export const ADD_OWNER_THRESHOLD_NEXT_BTN_TEST_ID = 'add-owner-threshold-next-btn'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
|
@ -110,7 +110,7 @@ owner(s)
|
||||||
variant="contained"
|
variant="contained"
|
||||||
minWidth={140}
|
minWidth={140}
|
||||||
color="primary"
|
color="primary"
|
||||||
testId={ADD_OWNER_THRESHOLD_NEXT_BTN_TESTID}
|
testId={ADD_OWNER_THRESHOLD_NEXT_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
Review
|
Review
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -20,8 +20,8 @@ import Modal from '~/components/Modal'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary } from '~/theme/variables'
|
||||||
|
|
||||||
export const RENAME_OWNER_INPUT_TESTID = 'rename-owner-input'
|
export const RENAME_OWNER_INPUT_TEST_ID = 'rename-owner-input'
|
||||||
export const SAVE_OWNER_CHANGES_BTN_TESTID = 'save-owner-changes-btn'
|
export const SAVE_OWNER_CHANGES_BTN_TEST_ID = 'save-owner-changes-btn'
|
||||||
|
|
||||||
const openIconStyle = {
|
const openIconStyle = {
|
||||||
height: '16px',
|
height: '16px',
|
||||||
|
@ -85,7 +85,7 @@ const EditOwnerComponent = ({
|
||||||
text="Owner name*"
|
text="Owner name*"
|
||||||
initialValue={selectedOwnerName}
|
initialValue={selectedOwnerName}
|
||||||
className={classes.addressInput}
|
className={classes.addressInput}
|
||||||
testId={RENAME_OWNER_INPUT_TESTID}
|
testId={RENAME_OWNER_INPUT_TEST_ID}
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -105,7 +105,7 @@ const EditOwnerComponent = ({
|
||||||
<Button className={classes.button} minWidth={140} onClick={onClose}>
|
<Button className={classes.button} minWidth={140} onClick={onClose}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="submit" className={classes.button} variant="contained" minWidth={140} color="primary" testId={SAVE_OWNER_CHANGES_BTN_TESTID}>
|
<Button type="submit" className={classes.button} variant="contained" minWidth={140} color="primary" testId={SAVE_OWNER_CHANGES_BTN_TEST_ID}>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary } from '~/theme/variables'
|
||||||
|
|
||||||
export const REMOVE_OWNER_MODAL_NEXT_BTN_TESTID = 'remove-owner-next-btn'
|
export const REMOVE_OWNER_MODAL_NEXT_BTN_TEST_ID = 'remove-owner-next-btn'
|
||||||
|
|
||||||
const openIconStyle = {
|
const openIconStyle = {
|
||||||
height: '16px',
|
height: '16px',
|
||||||
|
@ -95,7 +95,7 @@ const CheckOwner = ({
|
||||||
minWidth={140}
|
minWidth={140}
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
testId={REMOVE_OWNER_MODAL_NEXT_BTN_TESTID}
|
testId={REMOVE_OWNER_MODAL_NEXT_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
Next
|
Next
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary } from '~/theme/variables'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
export const REMOVE_OWNER_REVIEW_BTN_TESTID = 'remove-owner-review-btn'
|
export const REMOVE_OWNER_REVIEW_BTN_TEST_ID = 'remove-owner-review-btn'
|
||||||
|
|
||||||
const openIconStyle = {
|
const openIconStyle = {
|
||||||
height: '16px',
|
height: '16px',
|
||||||
|
@ -182,7 +182,7 @@ const ReviewRemoveOwner = ({
|
||||||
variant="contained"
|
variant="contained"
|
||||||
minWidth={140}
|
minWidth={140}
|
||||||
color="primary"
|
color="primary"
|
||||||
testId={REMOVE_OWNER_REVIEW_BTN_TESTID}
|
testId={REMOVE_OWNER_REVIEW_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
} from '~/components/forms/validator'
|
} from '~/components/forms/validator'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
export const REMOVE_OWNER_THRESHOLD_NEXT_BTN_TESTID = 'remove-owner-threshold-next-btn'
|
export const REMOVE_OWNER_THRESHOLD_NEXT_BTN_TEST_ID = 'remove-owner-threshold-next-btn'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
|
@ -114,7 +114,7 @@ owner(s)
|
||||||
variant="contained"
|
variant="contained"
|
||||||
minWidth={140}
|
minWidth={140}
|
||||||
color="primary"
|
color="primary"
|
||||||
data-testid={REMOVE_OWNER_THRESHOLD_NEXT_BTN_TESTID}
|
data-testid={REMOVE_OWNER_THRESHOLD_NEXT_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
Review
|
Review
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -29,9 +29,9 @@ import {
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary } from '~/theme/variables'
|
||||||
|
|
||||||
export const REPLACE_OWNER_NAME_INPUT_TESTID = 'replace-owner-name-input'
|
export const REPLACE_OWNER_NAME_INPUT_TEST_ID = 'replace-owner-name-input'
|
||||||
export const REPLACE_OWNER_ADDRESS_INPUT_TESTID = 'replace-owner-address-testid'
|
export const REPLACE_OWNER_ADDRESS_INPUT_TEST_ID = 'replace-owner-address-testid'
|
||||||
export const REPLACE_OWNER_NEXT_BTN_TESTID = 'replace-owner-next-btn'
|
export const REPLACE_OWNER_NEXT_BTN_TEST_ID = 'replace-owner-next-btn'
|
||||||
|
|
||||||
const openIconStyle = {
|
const openIconStyle = {
|
||||||
height: '16px',
|
height: '16px',
|
||||||
|
@ -114,7 +114,7 @@ const OwnerForm = ({
|
||||||
placeholder="Owner name*"
|
placeholder="Owner name*"
|
||||||
text="Owner name*"
|
text="Owner name*"
|
||||||
className={classes.addressInput}
|
className={classes.addressInput}
|
||||||
testId={REPLACE_OWNER_NAME_INPUT_TESTID}
|
testId={REPLACE_OWNER_NAME_INPUT_TEST_ID}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -128,7 +128,7 @@ const OwnerForm = ({
|
||||||
placeholder="Owner address*"
|
placeholder="Owner address*"
|
||||||
text="Owner address*"
|
text="Owner address*"
|
||||||
className={classes.addressInput}
|
className={classes.addressInput}
|
||||||
testId={REPLACE_OWNER_ADDRESS_INPUT_TESTID}
|
testId={REPLACE_OWNER_ADDRESS_INPUT_TEST_ID}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -144,7 +144,7 @@ const OwnerForm = ({
|
||||||
variant="contained"
|
variant="contained"
|
||||||
minWidth={140}
|
minWidth={140}
|
||||||
color="primary"
|
color="primary"
|
||||||
testId={REPLACE_OWNER_NEXT_BTN_TESTID}
|
testId={REPLACE_OWNER_NEXT_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
Next
|
Next
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { getEtherScanLink } from '~/logic/wallets/getWeb3'
|
||||||
import { secondary } from '~/theme/variables'
|
import { secondary } from '~/theme/variables'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
export const REPLACE_OWNER_SUBMIT_BTN_TESTID = 'replace-owner-submit-btn'
|
export const REPLACE_OWNER_SUBMIT_BTN_TEST_ID = 'replace-owner-submit-btn'
|
||||||
|
|
||||||
const openIconStyle = {
|
const openIconStyle = {
|
||||||
height: '16px',
|
height: '16px',
|
||||||
|
@ -210,7 +210,7 @@ const ReviewRemoveOwner = ({
|
||||||
variant="contained"
|
variant="contained"
|
||||||
minWidth={140}
|
minWidth={140}
|
||||||
color="primary"
|
color="primary"
|
||||||
testId={REPLACE_OWNER_SUBMIT_BTN_TESTID}
|
testId={REPLACE_OWNER_SUBMIT_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -28,11 +28,11 @@ import ReplaceOwnerIcon from './assets/icons/replace-owner.svg'
|
||||||
import RenameOwnerIcon from './assets/icons/rename-owner.svg'
|
import RenameOwnerIcon from './assets/icons/rename-owner.svg'
|
||||||
import RemoveOwnerIcon from '../assets/icons/bin.svg'
|
import RemoveOwnerIcon from '../assets/icons/bin.svg'
|
||||||
|
|
||||||
export const RENAME_OWNER_BTN_TESTID = 'rename-owner-btn'
|
export const RENAME_OWNER_BTN_TEST_ID = 'rename-owner-btn'
|
||||||
export const REMOVE_OWNER_BTN_TESTID = 'remove-owner-btn'
|
export const REMOVE_OWNER_BTN_TEST_ID = 'remove-owner-btn'
|
||||||
export const ADD_OWNER_BTN_TESTID = 'add-owner-btn'
|
export const ADD_OWNER_BTN_TEST_ID = 'add-owner-btn'
|
||||||
export const REPLACE_OWNER_BTN_TESTID = 'replace-owner-btn'
|
export const REPLACE_OWNER_BTN_TEST_ID = 'replace-owner-btn'
|
||||||
export const OWNERS_ROW_TESTID = 'owners-row'
|
export const OWNERS_ROW_TEST_ID = 'owners-row'
|
||||||
|
|
||||||
const controlsStyle = {
|
const controlsStyle = {
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
|
@ -144,7 +144,7 @@ class ManageOwners extends React.Component<Props, State> {
|
||||||
noBorder
|
noBorder
|
||||||
>
|
>
|
||||||
{(sortedData: Array<OwnerRow>) => sortedData.map((row: any, index: number) => (
|
{(sortedData: Array<OwnerRow>) => sortedData.map((row: any, index: number) => (
|
||||||
<TableRow tabIndex={-1} key={index} className={classes.hide} data-testid={OWNERS_ROW_TESTID}>
|
<TableRow tabIndex={-1} key={index} className={classes.hide} data-testid={OWNERS_ROW_TEST_ID}>
|
||||||
{autoColumns.map((column: Column) => (
|
{autoColumns.map((column: Column) => (
|
||||||
<TableCell key={column.id} style={cellWidth(column.width)} align={column.align} component="td">
|
<TableCell key={column.id} style={cellWidth(column.width)} align={column.align} component="td">
|
||||||
{column.id === OWNERS_TABLE_ADDRESS_ID ? (
|
{column.id === OWNERS_TABLE_ADDRESS_ID ? (
|
||||||
|
@ -162,14 +162,14 @@ class ManageOwners extends React.Component<Props, State> {
|
||||||
className={classes.editOwnerIcon}
|
className={classes.editOwnerIcon}
|
||||||
src={RenameOwnerIcon}
|
src={RenameOwnerIcon}
|
||||||
onClick={this.onShow('EditOwner', row)}
|
onClick={this.onShow('EditOwner', row)}
|
||||||
testId={RENAME_OWNER_BTN_TESTID}
|
testId={RENAME_OWNER_BTN_TEST_ID}
|
||||||
/>
|
/>
|
||||||
<Img
|
<Img
|
||||||
alt="Replace owner"
|
alt="Replace owner"
|
||||||
className={classes.replaceOwnerIcon}
|
className={classes.replaceOwnerIcon}
|
||||||
src={ReplaceOwnerIcon}
|
src={ReplaceOwnerIcon}
|
||||||
onClick={this.onShow('ReplaceOwner', row)}
|
onClick={this.onShow('ReplaceOwner', row)}
|
||||||
testId={REPLACE_OWNER_BTN_TESTID}
|
testId={REPLACE_OWNER_BTN_TEST_ID}
|
||||||
/>
|
/>
|
||||||
{ownerData.size > 1 && (
|
{ownerData.size > 1 && (
|
||||||
<Img
|
<Img
|
||||||
|
@ -177,7 +177,7 @@ class ManageOwners extends React.Component<Props, State> {
|
||||||
className={classes.removeOwnerIcon}
|
className={classes.removeOwnerIcon}
|
||||||
src={RemoveOwnerIcon}
|
src={RemoveOwnerIcon}
|
||||||
onClick={this.onShow('RemoveOwner', row)}
|
onClick={this.onShow('RemoveOwner', row)}
|
||||||
testId={REMOVE_OWNER_BTN_TESTID}
|
testId={REMOVE_OWNER_BTN_TEST_ID}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -199,7 +199,7 @@ class ManageOwners extends React.Component<Props, State> {
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={this.onShow('AddOwner')}
|
onClick={this.onShow('AddOwner')}
|
||||||
testId={ADD_OWNER_BTN_TESTID}
|
testId={ADD_OWNER_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
Add new owner
|
Add new owner
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -20,7 +20,7 @@ import actions, { type Actions } from './actions'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
import RemoveSafeIcon from './assets/icons/bin.svg'
|
import RemoveSafeIcon from './assets/icons/bin.svg'
|
||||||
|
|
||||||
export const OWNERS_SETTINGS_TAB_TESTID = 'owner-settings-tab'
|
export const OWNERS_SETTINGS_TAB_TEST_ID = 'owner-settings-tab'
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
showRemoveSafe: boolean,
|
showRemoveSafe: boolean,
|
||||||
|
@ -121,7 +121,7 @@ class Settings extends React.Component<Props, State> {
|
||||||
<Row
|
<Row
|
||||||
className={cn(classes.menuOption, menuOptionIndex === 2 && classes.active)}
|
className={cn(classes.menuOption, menuOptionIndex === 2 && classes.active)}
|
||||||
onClick={this.handleChange(2)}
|
onClick={this.handleChange(2)}
|
||||||
testId={OWNERS_SETTINGS_TAB_TESTID}
|
testId={OWNERS_SETTINGS_TAB_TEST_ID}
|
||||||
>
|
>
|
||||||
Owners (
|
Owners (
|
||||||
{owners.size}
|
{owners.size}
|
||||||
|
|
|
@ -5,8 +5,10 @@ import Col from '~/components/layout/Col'
|
||||||
import Row from '~/components/layout/Row'
|
import Row from '~/components/layout/Row'
|
||||||
import Paragraph from '~/components/layout/Paragraph/index'
|
import Paragraph from '~/components/layout/Paragraph/index'
|
||||||
|
|
||||||
|
export const NO_TRANSACTION_ROW_TEST_ID = 'no-transaction-row'
|
||||||
|
|
||||||
const NoTransactions = () => (
|
const NoTransactions = () => (
|
||||||
<Row>
|
<Row data-testid={NO_TRANSACTION_ROW_TEST_ID}>
|
||||||
<Col xs={12} center="xs" sm={10} smOffset={2} start="sm" margin="md">
|
<Col xs={12} center="xs" sm={10} smOffset={2} start="sm" margin="md">
|
||||||
<Paragraph size="lg">
|
<Paragraph size="lg">
|
||||||
<Bold>No transactions found for this safe</Bold>
|
<Bold>No transactions found for this safe</Bold>
|
||||||
|
|
|
@ -16,6 +16,8 @@ import Paragraph from '~/components/layout/Paragraph'
|
||||||
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
import { type Transaction } from '~/routes/safe/store/models/transaction'
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
|
export const APPROVE_TX_MODAL_SUBMIT_BTN_TEST_ID = 'approve-tx-modal-submit-btn'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
classes: Object,
|
classes: Object,
|
||||||
|
@ -113,6 +115,7 @@ const ApproveTxModal = ({
|
||||||
minHeight={42}
|
minHeight={42}
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={approveTx}
|
onClick={approveTx}
|
||||||
|
testId={APPROVE_TX_MODAL_SUBMIT_BTN_TEST_ID}
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -7,6 +7,9 @@ import Row from '~/components/layout/Row'
|
||||||
import Button from '~/components/layout/Button'
|
import Button from '~/components/layout/Button'
|
||||||
import { sm, lg } from '~/theme/variables'
|
import { sm, lg } from '~/theme/variables'
|
||||||
|
|
||||||
|
export const CONFIRM_TX_BTN_TEST_ID = 'confirm-btn'
|
||||||
|
export const EXECUTE_TX_BTN_TEST_ID = 'execute-btn'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onTxConfirm: Function,
|
onTxConfirm: Function,
|
||||||
onTxCancel: Function,
|
onTxCancel: Function,
|
||||||
|
@ -54,14 +57,28 @@ const ButtonRow = ({
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{showConfirmBtn && (
|
{showConfirmBtn && (
|
||||||
<Button className={classes.button} variant="contained" minWidth={140} color="primary" onClick={onTxConfirm}>
|
<Button
|
||||||
|
className={classes.button}
|
||||||
|
variant="contained"
|
||||||
|
minWidth={140}
|
||||||
|
color="primary"
|
||||||
|
onClick={onTxConfirm}
|
||||||
|
testId={CONFIRM_TX_BTN_TEST_ID}
|
||||||
|
>
|
||||||
<EditIcon className={classes.icon} />
|
<EditIcon className={classes.icon} />
|
||||||
{' '}
|
{' '}
|
||||||
Confirm TX
|
Confirm TX
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{showExecuteBtn && (
|
{showExecuteBtn && (
|
||||||
<Button className={classes.button} variant="contained" minWidth={140} color="primary" onClick={onTxExecute}>
|
<Button
|
||||||
|
className={classes.button}
|
||||||
|
variant="contained"
|
||||||
|
minWidth={140}
|
||||||
|
color="primary"
|
||||||
|
onClick={onTxExecute}
|
||||||
|
testId={EXECUTE_TX_BTN_TEST_ID}
|
||||||
|
>
|
||||||
<EditIcon className={classes.icon} />
|
<EditIcon className={classes.icon} />
|
||||||
{' '}
|
{' '}
|
||||||
Execute TX
|
Execute TX
|
||||||
|
|
|
@ -6,9 +6,14 @@ import Bold from '~/components/layout/Bold'
|
||||||
import EtherscanLink from '~/components/EtherscanLink'
|
import EtherscanLink from '~/components/EtherscanLink'
|
||||||
import Paragraph from '~/components/layout/Paragraph'
|
import Paragraph from '~/components/layout/Paragraph'
|
||||||
import Block from '~/components/layout/Block'
|
import Block from '~/components/layout/Block'
|
||||||
import { md, lg, secondary } from '~/theme/variables'
|
import { md, lg } from '~/theme/variables'
|
||||||
import { getTxData } from './utils'
|
import { getTxData } from './utils'
|
||||||
|
|
||||||
|
export const TRANSACTIONS_DESC_ADD_OWNER_TEST_ID = 'tx-description-add-owner'
|
||||||
|
export const TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID = 'tx-description-remove-owner'
|
||||||
|
export const TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID = 'tx-description-change-threshold'
|
||||||
|
export const TRANSACTIONS_DESC_SEND_TEST_ID = 'tx-description-send'
|
||||||
|
|
||||||
export const styles = () => ({
|
export const styles = () => ({
|
||||||
txDataContainer: {
|
txDataContainer: {
|
||||||
padding: `${lg} ${md}`,
|
padding: `${lg} ${md}`,
|
||||||
|
@ -33,7 +38,7 @@ type DescriptionDescProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const TransferDescription = ({ value = '', symbol, recipient }: TransferDescProps) => (
|
const TransferDescription = ({ value = '', symbol, recipient }: TransferDescProps) => (
|
||||||
<Paragraph noMargin>
|
<Paragraph noMargin data-testid={TRANSACTIONS_DESC_SEND_TEST_ID}>
|
||||||
<Bold>
|
<Bold>
|
||||||
Send
|
Send
|
||||||
{' '}
|
{' '}
|
||||||
|
@ -51,21 +56,21 @@ to:
|
||||||
const SettingsDescription = ({ removedOwner, addedOwner, newThreshold }: DescriptionDescProps) => (
|
const SettingsDescription = ({ removedOwner, addedOwner, newThreshold }: DescriptionDescProps) => (
|
||||||
<>
|
<>
|
||||||
{removedOwner && (
|
{removedOwner && (
|
||||||
<Paragraph>
|
<Paragraph data-testid={TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID}>
|
||||||
<Bold>Remove owner:</Bold>
|
<Bold>Remove owner:</Bold>
|
||||||
<br />
|
<br />
|
||||||
<EtherscanLink type="address" value={removedOwner} />
|
<EtherscanLink type="address" value={removedOwner} />
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
)}
|
)}
|
||||||
{addedOwner && (
|
{addedOwner && (
|
||||||
<Paragraph>
|
<Paragraph data-testid={TRANSACTIONS_DESC_ADD_OWNER_TEST_ID}>
|
||||||
<Bold>Add owner:</Bold>
|
<Bold>Add owner:</Bold>
|
||||||
<br />
|
<br />
|
||||||
<EtherscanLink type="address" value={addedOwner} />
|
<EtherscanLink type="address" value={addedOwner} />
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
)}
|
)}
|
||||||
{newThreshold && (
|
{newThreshold && (
|
||||||
<Paragraph>
|
<Paragraph data-testid={TRANSACTIONS_DESC_CHANGE_THRESHOLD_TEST_ID}>
|
||||||
<Bold>Change required confirmations:</Bold>
|
<Bold>Change required confirmations:</Bold>
|
||||||
<br />
|
<br />
|
||||||
{newThreshold}
|
{newThreshold}
|
||||||
|
|
|
@ -39,9 +39,9 @@ export const getTxData = (tx: Transaction): DecodedTxData => {
|
||||||
txData.addedOwner = tx.decodedParams.args[0]
|
txData.addedOwner = tx.decodedParams.args[0]
|
||||||
txData.newThreshold = tx.decodedParams.args[1]
|
txData.newThreshold = tx.decodedParams.args[1]
|
||||||
} else if (tx.decodedParams.methodName === 'swapOwner') {
|
} else if (tx.decodedParams.methodName === 'swapOwner') {
|
||||||
txData.addedOwner = tx.decodedParams.args[0]
|
txData.newThreshold = tx.decodedParams.args[0]
|
||||||
txData.removedOwner = tx.decodedParams.args[1]
|
txData.removedOwner = tx.decodedParams.args[1]
|
||||||
txData.newThreshold = tx.decodedParams.args[2]
|
txData.addedOwner = tx.decodedParams.args[2]
|
||||||
}
|
}
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ import {
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
import Status from './Status'
|
import Status from './Status'
|
||||||
|
|
||||||
|
export const TRANSACTION_ROW_TEST_ID = 'transaction-row'
|
||||||
|
|
||||||
const expandCellStyle = {
|
const expandCellStyle = {
|
||||||
paddingLeft: 0,
|
paddingLeft: 0,
|
||||||
paddingRight: 0,
|
paddingRight: 0,
|
||||||
|
@ -52,8 +54,8 @@ const TxsTable = ({
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [expandedTx, setExpandedTx] = useState<string | null>(null)
|
const [expandedTx, setExpandedTx] = useState<string | null>(null)
|
||||||
|
|
||||||
const handleTxExpand = (creationTxHash) => {
|
const handleTxExpand = (safeTxHash) => {
|
||||||
setExpandedTx(prevTx => (prevTx === creationTxHash ? null : creationTxHash))
|
setExpandedTx(prevTx => (prevTx === safeTxHash ? null : safeTxHash))
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns = generateColumns()
|
const columns = generateColumns()
|
||||||
|
@ -75,8 +77,9 @@ const TxsTable = ({
|
||||||
<React.Fragment key={index}>
|
<React.Fragment key={index}>
|
||||||
<TableRow
|
<TableRow
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className={cn(classes.row, expandedTx === row.tx.creationTxHash && classes.expandedRow)}
|
className={cn(classes.row, expandedTx === row.tx.safeTxHash && classes.expandedRow)}
|
||||||
onClick={() => handleTxExpand(row.tx.creationTxHash)}
|
onClick={() => handleTxExpand(row.tx.safeTxHash)}
|
||||||
|
data-testid={TRANSACTION_ROW_TEST_ID}
|
||||||
>
|
>
|
||||||
{autoColumns.map((column: Column) => (
|
{autoColumns.map((column: Column) => (
|
||||||
<TableCell
|
<TableCell
|
||||||
|
@ -95,7 +98,7 @@ const TxsTable = ({
|
||||||
</Row>
|
</Row>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell style={expandCellStyle}>
|
<TableCell style={expandCellStyle}>
|
||||||
<IconButton disableRipple>{expandedTx === row.nonce ? <ExpandLess /> : <ExpandMore />}</IconButton>
|
<IconButton disableRipple>{expandedTx === row.safeTxHash ? <ExpandLess /> : <ExpandMore />}</IconButton>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
@ -105,7 +108,7 @@ const TxsTable = ({
|
||||||
className={classes.extendedTxContainer}
|
className={classes.extendedTxContainer}
|
||||||
>
|
>
|
||||||
<Collapse
|
<Collapse
|
||||||
in={expandedTx === row.tx.creationTxHash}
|
in={expandedTx === row.tx.safeTxHash}
|
||||||
timeout="auto"
|
timeout="auto"
|
||||||
component={ExpandedTxComponent}
|
component={ExpandedTxComponent}
|
||||||
unmountOnExit
|
unmountOnExit
|
||||||
|
|
|
@ -14,6 +14,8 @@ export type Props = Actions &
|
||||||
const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 5000
|
const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 5000
|
||||||
|
|
||||||
class SafeView extends React.Component<Props> {
|
class SafeView extends React.Component<Props> {
|
||||||
|
intervalId: IntervalID
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {
|
const {
|
||||||
fetchSafe, activeTokens, safeUrl, fetchTokenBalances, fetchTokens,
|
fetchSafe, activeTokens, safeUrl, fetchTokenBalances, fetchTokens,
|
||||||
|
@ -44,15 +46,12 @@ class SafeView extends React.Component<Props> {
|
||||||
|
|
||||||
checkForUpdates() {
|
checkForUpdates() {
|
||||||
const {
|
const {
|
||||||
safeUrl, activeTokens, fetchSafe, fetchTokenBalances,
|
safeUrl, activeTokens, fetchTokenBalances,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
fetchSafe(safeUrl, true)
|
|
||||||
fetchTokenBalances(safeUrl, activeTokens)
|
fetchTokenBalances(safeUrl, activeTokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
intervalId: IntervalID
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
safe,
|
safe,
|
||||||
|
|
|
@ -34,9 +34,7 @@ const createTransaction = (
|
||||||
openSnackbar('Approval transaction has been confirmed', 'success')
|
openSnackbar('Approval transaction has been confirmed', 'success')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!process.env.NODE_ENV === 'test') {
|
dispatch(fetchTransactions(safeAddress))
|
||||||
dispatch(fetchTransactions(safeAddress))
|
|
||||||
}
|
|
||||||
|
|
||||||
return txHash
|
return txHash
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,11 @@ type TxServiceModel = {
|
||||||
isExecuted: boolean,
|
isExecuted: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildTransactionFrom = async (safeAddress: string, tx: TxServiceModel, safeSubjects: Map<string, string>) => {
|
export const buildTransactionFrom = async (
|
||||||
|
safeAddress: string,
|
||||||
|
tx: TxServiceModel,
|
||||||
|
safeSubjects: Map<string, string>,
|
||||||
|
) => {
|
||||||
const name = safeSubjects.get(String(tx.nonce)) || 'Unknown'
|
const name = safeSubjects.get(String(tx.nonce)) || 'Unknown'
|
||||||
const storedOwners = await getOwners(safeAddress)
|
const storedOwners = await getOwners(safeAddress)
|
||||||
const confirmations = List(
|
const confirmations = List(
|
||||||
|
@ -55,7 +59,6 @@ const buildTransactionFrom = async (safeAddress: string, tx: TxServiceModel, saf
|
||||||
const modifySettingsTx = tx.to === safeAddress && Number(tx.value) === 0 && !!tx.data
|
const modifySettingsTx = tx.to === safeAddress && Number(tx.value) === 0 && !!tx.data
|
||||||
const cancellationTx = tx.to === safeAddress && Number(tx.value) === 0 && !tx.data
|
const cancellationTx = tx.to === safeAddress && Number(tx.value) === 0 && !tx.data
|
||||||
const isTokenTransfer = await isAddressAToken(tx.to)
|
const isTokenTransfer = await isAddressAToken(tx.to)
|
||||||
const creationTxHash = confirmations.last().hash
|
|
||||||
|
|
||||||
let executionTxHash
|
let executionTxHash
|
||||||
const executionTx = confirmations.find(conf => conf.type === TX_TYPE_EXECUTION)
|
const executionTx = confirmations.find(conf => conf.type === TX_TYPE_EXECUTION)
|
||||||
|
@ -76,9 +79,7 @@ const buildTransactionFrom = async (safeAddress: string, tx: TxServiceModel, saf
|
||||||
recipient: params[0],
|
recipient: params[0],
|
||||||
value: params[1],
|
value: params[1],
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (modifySettingsTx && tx.data) {
|
||||||
modifySettingsTx && tx.data
|
|
||||||
) {
|
|
||||||
decodedParams = await decodeParamsFromSafeMethod(tx.data)
|
decodedParams = await decodeParamsFromSafeMethod(tx.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +95,7 @@ const buildTransactionFrom = async (safeAddress: string, tx: TxServiceModel, saf
|
||||||
submissionDate: tx.submissionDate,
|
submissionDate: tx.submissionDate,
|
||||||
executionDate: tx.executionDate,
|
executionDate: tx.executionDate,
|
||||||
executionTxHash,
|
executionTxHash,
|
||||||
creationTxHash,
|
safeTxHash: tx.safeTxHash,
|
||||||
isTokenTransfer,
|
isTokenTransfer,
|
||||||
decodedParams,
|
decodedParams,
|
||||||
modifySettingsTx,
|
modifySettingsTx,
|
||||||
|
|
|
@ -44,7 +44,6 @@ const processTransaction = (
|
||||||
const shouldExecute = threshold === tx.confirmations.size || approveAndExecute
|
const shouldExecute = threshold === tx.confirmations.size || approveAndExecute
|
||||||
const sigs = generateSignaturesFromTxConfirmations(tx, approveAndExecute && userAddress)
|
const sigs = generateSignaturesFromTxConfirmations(tx, approveAndExecute && userAddress)
|
||||||
|
|
||||||
|
|
||||||
let txHash
|
let txHash
|
||||||
if (shouldExecute) {
|
if (shouldExecute) {
|
||||||
openSnackbar('Transaction has been submitted', 'success')
|
openSnackbar('Transaction has been submitted', 'success')
|
||||||
|
@ -56,9 +55,7 @@ const processTransaction = (
|
||||||
openSnackbar('Approval transaction has been confirmed', 'success')
|
openSnackbar('Approval transaction has been confirmed', 'success')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!process.env.NODE_ENV === 'test') {
|
dispatch(fetchTransactions(safeAddress))
|
||||||
dispatch(fetchTransactions(safeAddress))
|
|
||||||
}
|
|
||||||
|
|
||||||
return txHash
|
return txHash
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ export type TransactionProps = {
|
||||||
symbol: string,
|
symbol: string,
|
||||||
modifySettingsTx: boolean,
|
modifySettingsTx: boolean,
|
||||||
cancellationTx: boolean,
|
cancellationTx: boolean,
|
||||||
creationTxHash: string,
|
safeTxHash: string,
|
||||||
executionTxHash?: string,
|
executionTxHash?: string,
|
||||||
cancelled?: boolean,
|
cancelled?: boolean,
|
||||||
status?: TransactionStatus,
|
status?: TransactionStatus,
|
||||||
|
@ -38,7 +38,7 @@ export const makeTransaction: RecordFactory<TransactionProps> = Record({
|
||||||
executionDate: '',
|
executionDate: '',
|
||||||
symbol: '',
|
symbol: '',
|
||||||
executionTxHash: undefined,
|
executionTxHash: undefined,
|
||||||
creationTxHash: '',
|
safeTxHash: '',
|
||||||
cancelled: false,
|
cancelled: false,
|
||||||
modifySettingsTx: false,
|
modifySettingsTx: false,
|
||||||
cancellationTx: false,
|
cancellationTx: false,
|
||||||
|
|
|
@ -13,11 +13,12 @@ import { calculateBalanceOf } from '~/routes/safe/store/actions/fetchTokenBalanc
|
||||||
import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens'
|
import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens'
|
||||||
import '@testing-library/jest-dom/extend-expect'
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
import updateSafe from '~/routes/safe/store/actions/updateSafe'
|
import updateSafe from '~/routes/safe/store/actions/updateSafe'
|
||||||
|
import { checkRegisteredTxSend, fillAndSubmitSendFundsForm } from './utils/transactions'
|
||||||
import { BALANCE_ROW_TEST_ID } from '~/routes/safe/components/Balances'
|
import { BALANCE_ROW_TEST_ID } from '~/routes/safe/components/Balances'
|
||||||
|
|
||||||
afterEach(cleanup)
|
afterEach(cleanup)
|
||||||
|
|
||||||
describe('DOM > Feature > Funds', () => {
|
describe('DOM > Feature > Sending Funds', () => {
|
||||||
let store
|
let store
|
||||||
let safeAddress: string
|
let safeAddress: string
|
||||||
let accounts
|
let accounts
|
||||||
|
@ -31,8 +32,11 @@ describe('DOM > Feature > Funds', () => {
|
||||||
it('Sends ETH with threshold = 1', async () => {
|
it('Sends ETH with threshold = 1', async () => {
|
||||||
// GIVEN
|
// GIVEN
|
||||||
const ethAmount = '5'
|
const ethAmount = '5'
|
||||||
await sendEtherTo(safeAddress, ethAmount)
|
|
||||||
const balanceAfterSendingEthToSafe = await getBalanceInEtherOf(accounts[0])
|
// the tests are run in parallel, lets use account 9 because it's not used anywhere else
|
||||||
|
// (in other tests we trigger transactions and pay gas for it, so we can't really make reliable
|
||||||
|
// assumptions on account's ETH balance)
|
||||||
|
await sendEtherTo(safeAddress, ethAmount, 9)
|
||||||
|
|
||||||
// WHEN
|
// WHEN
|
||||||
const SafeDom = renderSafeView(store, safeAddress)
|
const SafeDom = renderSafeView(store, safeAddress)
|
||||||
|
@ -44,29 +48,21 @@ describe('DOM > Feature > Funds', () => {
|
||||||
const sendButton = SafeDom.getByTestId('balance-send-btn')
|
const sendButton = SafeDom.getByTestId('balance-send-btn')
|
||||||
fireEvent.click(sendButton)
|
fireEvent.click(sendButton)
|
||||||
|
|
||||||
// Fill first send funds screen
|
const receiverBalanceBeforeTx = await getBalanceInEtherOf(accounts[9])
|
||||||
const recipientInput = SafeDom.getByPlaceholderText('Recipient*')
|
await fillAndSubmitSendFundsForm(SafeDom, sendButton, ethAmount, accounts[9])
|
||||||
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
|
// THEN
|
||||||
const safeFunds = await getBalanceInEtherOf(safeAddress)
|
const safeFunds = await getBalanceInEtherOf(safeAddress)
|
||||||
expect(Number(safeFunds)).toBe(0)
|
expect(Number(safeFunds)).toBe(0)
|
||||||
|
const receiverBalanceAfterTx = await getBalanceInEtherOf(accounts[9])
|
||||||
|
|
||||||
const receiverFunds = await getBalanceInEtherOf(accounts[0])
|
|
||||||
const ESTIMATED_GASCOSTS = 0.3
|
const ESTIMATED_GASCOSTS = 0.3
|
||||||
expect(Number(parseInt(receiverFunds, 10) - parseInt(balanceAfterSendingEthToSafe, 10))).toBeGreaterThan(
|
expect(Number(parseInt(receiverBalanceAfterTx, 10) - parseInt(receiverBalanceBeforeTx, 10))).toBeGreaterThan(
|
||||||
parseInt(ethAmount, 10) - ESTIMATED_GASCOSTS,
|
parseInt(ethAmount, 10) - ESTIMATED_GASCOSTS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Check that the transaction was registered
|
||||||
|
await checkRegisteredTxSend(SafeDom, ethAmount, 'ETH', accounts[9])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Sends Tokens with threshold = 1', async () => {
|
it('Sends Tokens with threshold = 1', async () => {
|
||||||
|
@ -97,26 +93,16 @@ describe('DOM > Feature > Funds', () => {
|
||||||
expect(balanceRows.length).toBe(2)
|
expect(balanceRows.length).toBe(2)
|
||||||
const sendButtons = SafeDom.getAllByTestId('balance-send-btn')
|
const sendButtons = SafeDom.getAllByTestId('balance-send-btn')
|
||||||
expect(sendButtons.length).toBe(2)
|
expect(sendButtons.length).toBe(2)
|
||||||
fireEvent.click(sendButtons[1])
|
|
||||||
|
|
||||||
// Fill first send funds screen
|
await fillAndSubmitSendFundsForm(SafeDom, sendButtons[1], tokensAmount, tokenReceiver)
|
||||||
const recipientInput = SafeDom.getByPlaceholderText('Recipient*')
|
|
||||||
const amountInput = SafeDom.getByPlaceholderText('Amount*')
|
|
||||||
const reviewBtn = SafeDom.getByTestId('review-tx-btn')
|
|
||||||
fireEvent.change(recipientInput, { target: { value: tokenReceiver } })
|
|
||||||
fireEvent.change(amountInput, { target: { value: tokensAmount } })
|
|
||||||
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
|
// THEN
|
||||||
const safeFunds = await calculateBalanceOf(tokenAddress, safeAddress, 18)
|
const safeFunds = await calculateBalanceOf(tokenAddress, safeAddress, 18)
|
||||||
expect(Number(safeFunds)).toBe(0)
|
expect(Number(safeFunds)).toBe(0)
|
||||||
const receiverFunds = await calculateBalanceOf(tokenAddress, tokenReceiver, 18)
|
const receiverFunds = await calculateBalanceOf(tokenAddress, tokenReceiver, 18)
|
||||||
expect(receiverFunds).toBe(tokensAmount)
|
expect(receiverFunds).toBe(tokensAmount)
|
||||||
|
|
||||||
|
// Check that the transaction was registered
|
||||||
|
await checkRegisteredTxSend(SafeDom, tokensAmount, 'OMG', tokenReceiver)
|
||||||
})
|
})
|
||||||
})
|
})
|
|
@ -0,0 +1,84 @@
|
||||||
|
// @flow
|
||||||
|
import { fireEvent, cleanup } from '@testing-library/react'
|
||||||
|
import { aNewStore } from '~/store'
|
||||||
|
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
||||||
|
import { sendEtherTo } from '~/test/utils/tokenMovements'
|
||||||
|
import { renderSafeView } from '~/test/builder/safe.dom.utils'
|
||||||
|
import { getWeb3, getBalanceInEtherOf } from '~/logic/wallets/getWeb3'
|
||||||
|
import { sleep } from '~/utils/timer'
|
||||||
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
|
import { BALANCE_ROW_TEST_ID } from '~/routes/safe/components/Balances'
|
||||||
|
import { fillAndSubmitSendFundsForm } from './utils/transactions'
|
||||||
|
import { TRANSACTIONS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout'
|
||||||
|
import { TRANSACTION_ROW_TEST_ID } from '~/routes/safe/components/TransactionsNew/TxsTable'
|
||||||
|
import { useTestAccountAt, resetTestAccount } from './utils/accounts'
|
||||||
|
import { CONFIRM_TX_BTN_TEST_ID, EXECUTE_TX_BTN_TEST_ID } from '~/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/OwnersColumn/ButtonRow'
|
||||||
|
import { APPROVE_TX_MODAL_SUBMIT_BTN_TEST_ID } from '~/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/ApproveTxModal'
|
||||||
|
|
||||||
|
afterEach(cleanup)
|
||||||
|
afterEach(resetTestAccount)
|
||||||
|
|
||||||
|
describe('DOM > Feature > Sending Funds', () => {
|
||||||
|
let store
|
||||||
|
let safeAddress: string
|
||||||
|
let accounts
|
||||||
|
beforeEach(async () => {
|
||||||
|
store = aNewStore()
|
||||||
|
// using 4th account because other accounts were used in other tests and paid gas
|
||||||
|
safeAddress = await aMinedSafe(store, 2, 2)
|
||||||
|
accounts = await getWeb3().eth.getAccounts()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Sends ETH with threshold = 2', async () => {
|
||||||
|
// GIVEN
|
||||||
|
const ethAmount = '5'
|
||||||
|
await sendEtherTo(safeAddress, ethAmount)
|
||||||
|
const balanceAfterSendingEthToSafe = await getBalanceInEtherOf(accounts[0])
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
const SafeDom = renderSafeView(store, safeAddress)
|
||||||
|
await sleep(1300)
|
||||||
|
|
||||||
|
// Open send funds modal
|
||||||
|
const balanceRows = SafeDom.getAllByTestId(BALANCE_ROW_TEST_ID)
|
||||||
|
expect(balanceRows[0]).toHaveTextContent(`${ethAmount} ETH`)
|
||||||
|
const sendButton = SafeDom.getByTestId('balance-send-btn')
|
||||||
|
fireEvent.click(sendButton)
|
||||||
|
|
||||||
|
await fillAndSubmitSendFundsForm(SafeDom, sendButton, ethAmount, accounts[0])
|
||||||
|
|
||||||
|
// CONFIRM TX
|
||||||
|
fireEvent.click(SafeDom.getByTestId(TRANSACTIONS_TAB_BTN_TEST_ID))
|
||||||
|
await sleep(200)
|
||||||
|
|
||||||
|
useTestAccountAt(1)
|
||||||
|
await sleep(2200)
|
||||||
|
const txRows = SafeDom.getAllByTestId(TRANSACTION_ROW_TEST_ID)
|
||||||
|
expect(txRows.length).toBe(1)
|
||||||
|
|
||||||
|
fireEvent.click(txRows[0])
|
||||||
|
await sleep(100)
|
||||||
|
fireEvent.click(SafeDom.getByTestId(CONFIRM_TX_BTN_TEST_ID))
|
||||||
|
await sleep(100)
|
||||||
|
|
||||||
|
// Travel confirm modal
|
||||||
|
fireEvent.click(SafeDom.getByTestId(APPROVE_TX_MODAL_SUBMIT_BTN_TEST_ID))
|
||||||
|
await sleep(2000)
|
||||||
|
|
||||||
|
// EXECUTE TX
|
||||||
|
fireEvent.click(SafeDom.getByTestId(EXECUTE_TX_BTN_TEST_ID))
|
||||||
|
await sleep(100)
|
||||||
|
fireEvent.click(SafeDom.getByTestId(APPROVE_TX_MODAL_SUBMIT_BTN_TEST_ID))
|
||||||
|
await sleep(500)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
const safeFunds = await getBalanceInEtherOf(safeAddress)
|
||||||
|
expect(Number(safeFunds)).toBe(0)
|
||||||
|
|
||||||
|
const receiverFunds = await getBalanceInEtherOf(accounts[0])
|
||||||
|
const ESTIMATED_GASCOSTS = 0.3
|
||||||
|
expect(Number(parseInt(receiverFunds, 10) - parseInt(balanceAfterSendingEthToSafe, 10))).toBeGreaterThan(
|
||||||
|
parseInt(ethAmount, 10) - ESTIMATED_GASCOSTS,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
|
@ -5,8 +5,8 @@ import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
||||||
import { renderSafeView } from '~/test/builder/safe.dom.utils'
|
import { renderSafeView } from '~/test/builder/safe.dom.utils'
|
||||||
import { sleep } from '~/utils/timer'
|
import { sleep } from '~/utils/timer'
|
||||||
import '@testing-library/jest-dom/extend-expect'
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
import { SETTINGS_TAB_BTN_TESTID, SAFE_VIEW_NAME_HEADING_TESTID } from '~/routes/safe/components/Layout'
|
import { SETTINGS_TAB_BTN_TEST_ID, SAFE_VIEW_NAME_HEADING_TEST_ID } from '~/routes/safe/components/Layout'
|
||||||
import { SAFE_NAME_INPUT_TESTID, SAFE_NAME_SUBMIT_BTN_TESTID } from '~/routes/safe/components/Settings/ChangeSafeName'
|
import { SAFE_NAME_INPUT_TEST_ID, SAFE_NAME_SUBMIT_BTN_TEST_ID } from '~/routes/safe/components/Settings/ChangeSafeName'
|
||||||
|
|
||||||
afterEach(cleanup)
|
afterEach(cleanup)
|
||||||
|
|
||||||
|
@ -26,17 +26,17 @@ describe('DOM > Feature > Settings - Name', () => {
|
||||||
const SafeDom = renderSafeView(store, safeAddress)
|
const SafeDom = renderSafeView(store, safeAddress)
|
||||||
await sleep(1300)
|
await sleep(1300)
|
||||||
|
|
||||||
const safeNameHeading = SafeDom.getByTestId(SAFE_VIEW_NAME_HEADING_TESTID)
|
const safeNameHeading = SafeDom.getByTestId(SAFE_VIEW_NAME_HEADING_TEST_ID)
|
||||||
expect(safeNameHeading).toHaveTextContent(INITIAL_NAME)
|
expect(safeNameHeading).toHaveTextContent(INITIAL_NAME)
|
||||||
|
|
||||||
// Open settings tab
|
// Open settings tab
|
||||||
// Safe name setting screen should be pre-selected
|
// Safe name setting screen should be pre-selected
|
||||||
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TESTID)
|
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TEST_ID)
|
||||||
fireEvent.click(settingsBtn)
|
fireEvent.click(settingsBtn)
|
||||||
|
|
||||||
// Change the name
|
// Change the name
|
||||||
const safeNameInput = SafeDom.getByTestId(SAFE_NAME_INPUT_TESTID)
|
const safeNameInput = SafeDom.getByTestId(SAFE_NAME_INPUT_TEST_ID)
|
||||||
const submitBtn = SafeDom.getByTestId(SAFE_NAME_SUBMIT_BTN_TESTID)
|
const submitBtn = SafeDom.getByTestId(SAFE_NAME_SUBMIT_BTN_TEST_ID)
|
||||||
fireEvent.change(safeNameInput, { target: { value: NEW_NAME } })
|
fireEvent.change(safeNameInput, { target: { value: NEW_NAME } })
|
||||||
fireEvent.click(submitBtn)
|
fireEvent.click(submitBtn)
|
||||||
|
|
||||||
|
|
|
@ -5,35 +5,40 @@ import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
||||||
import { renderSafeView } from '~/test/builder/safe.dom.utils'
|
import { renderSafeView } from '~/test/builder/safe.dom.utils'
|
||||||
import { sleep } from '~/utils/timer'
|
import { sleep } from '~/utils/timer'
|
||||||
import '@testing-library/jest-dom/extend-expect'
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
import { SETTINGS_TAB_BTN_TESTID } from '~/routes/safe/components/Layout'
|
|
||||||
import { OWNERS_SETTINGS_TAB_TESTID } from '~/routes/safe/components/Settings'
|
|
||||||
import {
|
import {
|
||||||
RENAME_OWNER_BTN_TESTID,
|
checkRegisteredTxAddOwner,
|
||||||
OWNERS_ROW_TESTID,
|
checkRegisteredTxRemoveOwner,
|
||||||
REMOVE_OWNER_BTN_TESTID,
|
checkRegisteredTxReplaceOwner,
|
||||||
ADD_OWNER_BTN_TESTID,
|
} from './utils/transactions'
|
||||||
REPLACE_OWNER_BTN_TESTID,
|
import { SETTINGS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout'
|
||||||
|
import { OWNERS_SETTINGS_TAB_TEST_ID } from '~/routes/safe/components/Settings'
|
||||||
|
import {
|
||||||
|
RENAME_OWNER_BTN_TEST_ID,
|
||||||
|
OWNERS_ROW_TEST_ID,
|
||||||
|
REMOVE_OWNER_BTN_TEST_ID,
|
||||||
|
ADD_OWNER_BTN_TEST_ID,
|
||||||
|
REPLACE_OWNER_BTN_TEST_ID,
|
||||||
} from '~/routes/safe/components/Settings/ManageOwners'
|
} from '~/routes/safe/components/Settings/ManageOwners'
|
||||||
import {
|
import {
|
||||||
RENAME_OWNER_INPUT_TESTID,
|
RENAME_OWNER_INPUT_TEST_ID,
|
||||||
SAVE_OWNER_CHANGES_BTN_TESTID,
|
SAVE_OWNER_CHANGES_BTN_TEST_ID,
|
||||||
} from '~/routes/safe/components/Settings/ManageOwners/EditOwnerModal'
|
} from '~/routes/safe/components/Settings/ManageOwners/EditOwnerModal'
|
||||||
import { REMOVE_OWNER_MODAL_NEXT_BTN_TESTID } from '~/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner'
|
import { REMOVE_OWNER_MODAL_NEXT_BTN_TEST_ID } from '~/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/CheckOwner'
|
||||||
import { REMOVE_OWNER_THRESHOLD_NEXT_BTN_TESTID } from '~/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/ThresholdForm'
|
import { REMOVE_OWNER_THRESHOLD_NEXT_BTN_TEST_ID } from '~/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/ThresholdForm'
|
||||||
import { REMOVE_OWNER_REVIEW_BTN_TESTID } from '~/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review'
|
import { REMOVE_OWNER_REVIEW_BTN_TEST_ID } from '~/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review'
|
||||||
import { ADD_OWNER_THRESHOLD_NEXT_BTN_TESTID } from '~/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/ThresholdForm'
|
import { ADD_OWNER_THRESHOLD_NEXT_BTN_TEST_ID } from '~/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/ThresholdForm'
|
||||||
import {
|
import {
|
||||||
ADD_OWNER_NAME_INPUT_TESTID,
|
ADD_OWNER_NAME_INPUT_TEST_ID,
|
||||||
ADD_OWNER_ADDRESS_INPUT_TESTID,
|
ADD_OWNER_ADDRESS_INPUT_TEST_ID,
|
||||||
ADD_OWNER_NEXT_BTN_TESTID,
|
ADD_OWNER_NEXT_BTN_TEST_ID,
|
||||||
} from '~/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm'
|
} from '~/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm'
|
||||||
import { ADD_OWNER_SUBMIT_BTN_TESTID } from '~/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review'
|
import { ADD_OWNER_SUBMIT_BTN_TEST_ID } from '~/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review'
|
||||||
import {
|
import {
|
||||||
REPLACE_OWNER_NEXT_BTN_TESTID,
|
REPLACE_OWNER_NEXT_BTN_TEST_ID,
|
||||||
REPLACE_OWNER_NAME_INPUT_TESTID,
|
REPLACE_OWNER_NAME_INPUT_TEST_ID,
|
||||||
REPLACE_OWNER_ADDRESS_INPUT_TESTID,
|
REPLACE_OWNER_ADDRESS_INPUT_TEST_ID,
|
||||||
} from '~/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm'
|
} from '~/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm'
|
||||||
import { REPLACE_OWNER_SUBMIT_BTN_TESTID } from '~/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review'
|
import { REPLACE_OWNER_SUBMIT_BTN_TEST_ID } from '~/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review'
|
||||||
|
|
||||||
afterEach(cleanup)
|
afterEach(cleanup)
|
||||||
|
|
||||||
|
@ -52,28 +57,28 @@ describe('DOM > Feature > Settings - Manage owners', () => {
|
||||||
await sleep(1300)
|
await sleep(1300)
|
||||||
|
|
||||||
// Travel to settings
|
// Travel to settings
|
||||||
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TESTID)
|
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TEST_ID)
|
||||||
fireEvent.click(settingsBtn)
|
fireEvent.click(settingsBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// click on owners settings
|
// click on owners settings
|
||||||
const ownersSettingsBtn = SafeDom.getByTestId(OWNERS_SETTINGS_TAB_TESTID)
|
const ownersSettingsBtn = SafeDom.getByTestId(OWNERS_SETTINGS_TAB_TEST_ID)
|
||||||
fireEvent.click(ownersSettingsBtn)
|
fireEvent.click(ownersSettingsBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// open rename owner modal
|
// open rename owner modal
|
||||||
const renameOwnerBtn = SafeDom.getByTestId(RENAME_OWNER_BTN_TESTID)
|
const renameOwnerBtn = SafeDom.getByTestId(RENAME_OWNER_BTN_TEST_ID)
|
||||||
fireEvent.click(renameOwnerBtn)
|
fireEvent.click(renameOwnerBtn)
|
||||||
|
|
||||||
// rename owner
|
// rename owner
|
||||||
const ownerNameInput = SafeDom.getByTestId(RENAME_OWNER_INPUT_TESTID)
|
const ownerNameInput = SafeDom.getByTestId(RENAME_OWNER_INPUT_TEST_ID)
|
||||||
const saveOwnerChangesBtn = SafeDom.getByTestId(SAVE_OWNER_CHANGES_BTN_TESTID)
|
const saveOwnerChangesBtn = SafeDom.getByTestId(SAVE_OWNER_CHANGES_BTN_TEST_ID)
|
||||||
fireEvent.change(ownerNameInput, { target: { value: NEW_OWNER_NAME } })
|
fireEvent.change(ownerNameInput, { target: { value: NEW_OWNER_NAME } })
|
||||||
fireEvent.click(saveOwnerChangesBtn)
|
fireEvent.click(saveOwnerChangesBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// check if the name updated
|
// check if the name updated
|
||||||
const ownerRow = SafeDom.getByTestId(OWNERS_ROW_TESTID)
|
const ownerRow = SafeDom.getByTestId(OWNERS_ROW_TEST_ID)
|
||||||
expect(ownerRow).toHaveTextContent(NEW_OWNER_NAME)
|
expect(ownerRow).toHaveTextContent(NEW_OWNER_NAME)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -84,17 +89,17 @@ describe('DOM > Feature > Settings - Manage owners', () => {
|
||||||
await sleep(1300)
|
await sleep(1300)
|
||||||
|
|
||||||
// Travel to settings
|
// Travel to settings
|
||||||
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TESTID)
|
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TEST_ID)
|
||||||
fireEvent.click(settingsBtn)
|
fireEvent.click(settingsBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// click on owners settings
|
// click on owners settings
|
||||||
const ownersSettingsBtn = SafeDom.getByTestId(OWNERS_SETTINGS_TAB_TESTID)
|
const ownersSettingsBtn = SafeDom.getByTestId(OWNERS_SETTINGS_TAB_TEST_ID)
|
||||||
fireEvent.click(ownersSettingsBtn)
|
fireEvent.click(ownersSettingsBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// check if there are 2 owners
|
// check if there are 2 owners
|
||||||
let ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TESTID)
|
let ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TEST_ID)
|
||||||
expect(ownerRows.length).toBe(2)
|
expect(ownerRows.length).toBe(2)
|
||||||
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
||||||
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
||||||
|
@ -102,25 +107,28 @@ describe('DOM > Feature > Settings - Manage owners', () => {
|
||||||
expect(ownerRows[1]).toHaveTextContent('0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0')
|
expect(ownerRows[1]).toHaveTextContent('0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0')
|
||||||
|
|
||||||
// click remove owner btn which opens the modal
|
// click remove owner btn which opens the modal
|
||||||
const removeOwnerBtn = SafeDom.getAllByTestId(REMOVE_OWNER_BTN_TESTID)[1]
|
const removeOwnerBtn = SafeDom.getAllByTestId(REMOVE_OWNER_BTN_TEST_ID)[1]
|
||||||
fireEvent.click(removeOwnerBtn)
|
fireEvent.click(removeOwnerBtn)
|
||||||
|
|
||||||
// modal navigation
|
// modal navigation
|
||||||
const nextBtnStep1 = SafeDom.getByTestId(REMOVE_OWNER_MODAL_NEXT_BTN_TESTID)
|
const nextBtnStep1 = SafeDom.getByTestId(REMOVE_OWNER_MODAL_NEXT_BTN_TEST_ID)
|
||||||
fireEvent.click(nextBtnStep1)
|
fireEvent.click(nextBtnStep1)
|
||||||
|
|
||||||
const nextBtnStep2 = SafeDom.getByTestId(REMOVE_OWNER_THRESHOLD_NEXT_BTN_TESTID)
|
const nextBtnStep2 = SafeDom.getByTestId(REMOVE_OWNER_THRESHOLD_NEXT_BTN_TEST_ID)
|
||||||
fireEvent.click(nextBtnStep2)
|
fireEvent.click(nextBtnStep2)
|
||||||
|
|
||||||
const nextBtnStep3 = SafeDom.getByTestId(REMOVE_OWNER_REVIEW_BTN_TESTID)
|
const nextBtnStep3 = SafeDom.getByTestId(REMOVE_OWNER_REVIEW_BTN_TEST_ID)
|
||||||
fireEvent.click(nextBtnStep3)
|
fireEvent.click(nextBtnStep3)
|
||||||
await sleep(1300)
|
await sleep(1300)
|
||||||
|
|
||||||
// check if owner was removed
|
// check if owner was removed
|
||||||
ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TESTID)
|
ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TEST_ID)
|
||||||
expect(ownerRows.length).toBe(1)
|
expect(ownerRows.length).toBe(1)
|
||||||
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
||||||
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
||||||
|
|
||||||
|
// Check that the transaction was registered
|
||||||
|
await checkRegisteredTxRemoveOwner(SafeDom, '0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Adds a new owner', async () => {
|
it('Adds a new owner', async () => {
|
||||||
|
@ -131,46 +139,49 @@ describe('DOM > Feature > Settings - Manage owners', () => {
|
||||||
await sleep(1300)
|
await sleep(1300)
|
||||||
|
|
||||||
// Travel to settings
|
// Travel to settings
|
||||||
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TESTID)
|
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TEST_ID)
|
||||||
fireEvent.click(settingsBtn)
|
fireEvent.click(settingsBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// click on owners settings
|
// click on owners settings
|
||||||
const ownersSettingsBtn = SafeDom.getByTestId(OWNERS_SETTINGS_TAB_TESTID)
|
const ownersSettingsBtn = SafeDom.getByTestId(OWNERS_SETTINGS_TAB_TEST_ID)
|
||||||
fireEvent.click(ownersSettingsBtn)
|
fireEvent.click(ownersSettingsBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// check if there is 1 owner
|
// check if there is 1 owner
|
||||||
let ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TESTID)
|
let ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TEST_ID)
|
||||||
expect(ownerRows.length).toBe(1)
|
expect(ownerRows.length).toBe(1)
|
||||||
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
||||||
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
||||||
|
|
||||||
// click add owner btn
|
// click add owner btn
|
||||||
fireEvent.click(SafeDom.getByTestId(ADD_OWNER_BTN_TESTID))
|
fireEvent.click(SafeDom.getByTestId(ADD_OWNER_BTN_TEST_ID))
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// fill and travel add owner modal
|
// fill and travel add owner modal
|
||||||
const ownerNameInput = SafeDom.getByTestId(ADD_OWNER_NAME_INPUT_TESTID)
|
const ownerNameInput = SafeDom.getByTestId(ADD_OWNER_NAME_INPUT_TEST_ID)
|
||||||
const ownerAddressInput = SafeDom.getByTestId(ADD_OWNER_ADDRESS_INPUT_TESTID)
|
const ownerAddressInput = SafeDom.getByTestId(ADD_OWNER_ADDRESS_INPUT_TEST_ID)
|
||||||
const nextBtn = SafeDom.getByTestId(ADD_OWNER_NEXT_BTN_TESTID)
|
const nextBtn = SafeDom.getByTestId(ADD_OWNER_NEXT_BTN_TEST_ID)
|
||||||
fireEvent.change(ownerNameInput, { target: { value: NEW_OWNER_NAME } })
|
fireEvent.change(ownerNameInput, { target: { value: NEW_OWNER_NAME } })
|
||||||
fireEvent.change(ownerAddressInput, { target: { value: NEW_OWNER_ADDRESS } })
|
fireEvent.change(ownerAddressInput, { target: { value: NEW_OWNER_ADDRESS } })
|
||||||
fireEvent.click(nextBtn)
|
fireEvent.click(nextBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
fireEvent.click(SafeDom.getByTestId(ADD_OWNER_THRESHOLD_NEXT_BTN_TESTID))
|
fireEvent.click(SafeDom.getByTestId(ADD_OWNER_THRESHOLD_NEXT_BTN_TEST_ID))
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
fireEvent.click(SafeDom.getByTestId(ADD_OWNER_SUBMIT_BTN_TESTID))
|
fireEvent.click(SafeDom.getByTestId(ADD_OWNER_SUBMIT_BTN_TEST_ID))
|
||||||
await sleep(1500)
|
await sleep(1500)
|
||||||
|
|
||||||
// check if owner was added
|
// check if owner was added
|
||||||
ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TESTID)
|
ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TEST_ID)
|
||||||
expect(ownerRows.length).toBe(2)
|
expect(ownerRows.length).toBe(2)
|
||||||
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
||||||
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
||||||
expect(ownerRows[1]).toHaveTextContent(NEW_OWNER_NAME)
|
expect(ownerRows[1]).toHaveTextContent(NEW_OWNER_NAME)
|
||||||
expect(ownerRows[1]).toHaveTextContent(NEW_OWNER_ADDRESS)
|
expect(ownerRows[1]).toHaveTextContent(NEW_OWNER_ADDRESS)
|
||||||
|
|
||||||
|
// Check that the transaction was registered
|
||||||
|
await checkRegisteredTxAddOwner(SafeDom, NEW_OWNER_ADDRESS)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Replaces an owner', async () => {
|
it('Replaces an owner', async () => {
|
||||||
|
@ -183,17 +194,17 @@ describe('DOM > Feature > Settings - Manage owners', () => {
|
||||||
await sleep(1300)
|
await sleep(1300)
|
||||||
|
|
||||||
// Travel to settings
|
// Travel to settings
|
||||||
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TESTID)
|
const settingsBtn = SafeDom.getByTestId(SETTINGS_TAB_BTN_TEST_ID)
|
||||||
fireEvent.click(settingsBtn)
|
fireEvent.click(settingsBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// click on owners settings
|
// click on owners settings
|
||||||
const ownersSettingsBtn = SafeDom.getByTestId(OWNERS_SETTINGS_TAB_TESTID)
|
const ownersSettingsBtn = SafeDom.getByTestId(OWNERS_SETTINGS_TAB_TEST_ID)
|
||||||
fireEvent.click(ownersSettingsBtn)
|
fireEvent.click(ownersSettingsBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
// check if there are 2 owners
|
// check if there are 2 owners
|
||||||
let ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TESTID)
|
let ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TEST_ID)
|
||||||
expect(ownerRows.length).toBe(2)
|
expect(ownerRows.length).toBe(2)
|
||||||
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
||||||
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
||||||
|
@ -201,28 +212,31 @@ describe('DOM > Feature > Settings - Manage owners', () => {
|
||||||
expect(ownerRows[1]).toHaveTextContent('0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0')
|
expect(ownerRows[1]).toHaveTextContent('0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0')
|
||||||
|
|
||||||
// click replace owner btn which opens the modal
|
// click replace owner btn which opens the modal
|
||||||
const replaceOwnerBtn = SafeDom.getAllByTestId(REPLACE_OWNER_BTN_TESTID)[1]
|
const replaceOwnerBtn = SafeDom.getAllByTestId(REPLACE_OWNER_BTN_TEST_ID)[1]
|
||||||
fireEvent.click(replaceOwnerBtn)
|
fireEvent.click(replaceOwnerBtn)
|
||||||
|
|
||||||
// fill and travel add owner modal
|
// fill and travel add owner modal
|
||||||
const ownerNameInput = SafeDom.getByTestId(REPLACE_OWNER_NAME_INPUT_TESTID)
|
const ownerNameInput = SafeDom.getByTestId(REPLACE_OWNER_NAME_INPUT_TEST_ID)
|
||||||
const ownerAddressInput = SafeDom.getByTestId(REPLACE_OWNER_ADDRESS_INPUT_TESTID)
|
const ownerAddressInput = SafeDom.getByTestId(REPLACE_OWNER_ADDRESS_INPUT_TEST_ID)
|
||||||
const nextBtn = SafeDom.getByTestId(REPLACE_OWNER_NEXT_BTN_TESTID)
|
const nextBtn = SafeDom.getByTestId(REPLACE_OWNER_NEXT_BTN_TEST_ID)
|
||||||
fireEvent.change(ownerNameInput, { target: { value: NEW_OWNER_NAME } })
|
fireEvent.change(ownerNameInput, { target: { value: NEW_OWNER_NAME } })
|
||||||
fireEvent.change(ownerAddressInput, { target: { value: NEW_OWNER_ADDRESS } })
|
fireEvent.change(ownerAddressInput, { target: { value: NEW_OWNER_ADDRESS } })
|
||||||
fireEvent.click(nextBtn)
|
fireEvent.click(nextBtn)
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
|
|
||||||
const replaceSubmitBtn = SafeDom.getByTestId(REPLACE_OWNER_SUBMIT_BTN_TESTID)
|
const replaceSubmitBtn = SafeDom.getByTestId(REPLACE_OWNER_SUBMIT_BTN_TEST_ID)
|
||||||
fireEvent.click(replaceSubmitBtn)
|
fireEvent.click(replaceSubmitBtn)
|
||||||
await sleep(1000)
|
await sleep(1000)
|
||||||
|
|
||||||
// check if the owner was replaced
|
// check if the owner was replaced
|
||||||
ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TESTID)
|
ownerRows = SafeDom.getAllByTestId(OWNERS_ROW_TEST_ID)
|
||||||
expect(ownerRows.length).toBe(2)
|
expect(ownerRows.length).toBe(2)
|
||||||
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
expect(ownerRows[0]).toHaveTextContent('Adol 1 Eth Account')
|
||||||
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
expect(ownerRows[0]).toHaveTextContent('0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1')
|
||||||
expect(ownerRows[1]).toHaveTextContent(NEW_OWNER_NAME)
|
expect(ownerRows[1]).toHaveTextContent(NEW_OWNER_NAME)
|
||||||
expect(ownerRows[1]).toHaveTextContent(NEW_OWNER_ADDRESS)
|
expect(ownerRows[1]).toHaveTextContent(NEW_OWNER_ADDRESS)
|
||||||
|
|
||||||
|
// Check that the transaction was registered
|
||||||
|
await checkRegisteredTxReplaceOwner(SafeDom, '0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0', NEW_OWNER_ADDRESS)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
// TBD
|
|
||||||
|
|
||||||
describe('DOM > Feature > SAFE MULTISIG Transactions', () => {
|
|
||||||
it.only('mines correctly all multisig txs in a 1 owner & 1 threshold safe', async () => {})
|
|
||||||
|
|
||||||
it.only('mines withdraw process correctly all multisig txs in a 2 owner & 2 threshold safe', async () => {})
|
|
||||||
|
|
||||||
it.only('approves and executes pending transactions', async () => {})
|
|
||||||
})
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
// @flow
|
||||||
|
function useTestAccountAt(index: number = 0) {
|
||||||
|
window.testAccountIndex = index
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetTestAccount() {
|
||||||
|
delete window.testAccountIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
useTestAccountAt,
|
||||||
|
resetTestAccount,
|
||||||
|
}
|
|
@ -6,11 +6,11 @@ import { toNative } from '~/logic/wallets/tokens'
|
||||||
import TokenOMG from '../../../build/contracts/TokenOMG'
|
import TokenOMG from '../../../build/contracts/TokenOMG'
|
||||||
import TokenRDN from '../../../build/contracts/TokenRDN'
|
import TokenRDN from '../../../build/contracts/TokenRDN'
|
||||||
|
|
||||||
export const sendEtherTo = async (address: string, eth: string) => {
|
export const sendEtherTo = async (address: string, eth: string, fromAccountIndex: number = 0) => {
|
||||||
const web3 = getWeb3()
|
const web3 = getWeb3()
|
||||||
const accounts = await web3.eth.getAccounts()
|
const accounts = await web3.eth.getAccounts()
|
||||||
const { toBN, toWei } = web3.utils
|
const { toBN, toWei } = web3.utils
|
||||||
const txData = { from: accounts[0], to: address, value: toBN(toWei(eth, 'ether')) }
|
const txData = { from: accounts[fromAccountIndex], to: address, value: toBN(toWei(eth, 'ether')) }
|
||||||
return web3.eth.sendTransaction(txData)
|
return web3.eth.sendTransaction(txData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
export * from './moveFunds.helper'
|
||||||
|
export * from './moveTokens.helper'
|
||||||
|
export * from './threshold.helper'
|
||||||
|
export * from './transactionList.helper'
|
|
@ -1,52 +1,30 @@
|
||||||
// @flow
|
// @flow
|
||||||
import TestUtils from 'react-dom/test-utils'
|
import * as React from 'react'
|
||||||
|
import { fireEvent } from '@testing-library/react'
|
||||||
import { sleep } from '~/utils/timer'
|
import { sleep } from '~/utils/timer'
|
||||||
import { checkMinedTx, checkPendingTx } from '~/test/builder/safe.dom.utils'
|
|
||||||
import SendToken from '~/routes/safe/components/SendToken'
|
|
||||||
import { whenExecuted } from '~/test/utils/logTransactions'
|
|
||||||
|
|
||||||
export const sendMoveFundsForm = async (
|
export const fillAndSubmitSendFundsForm = async (
|
||||||
SafeDom: React.Component<any, any>,
|
SafeDom: any,
|
||||||
expandBalance: React.Component<any, any>,
|
sendButton: React.Component<any, any>,
|
||||||
value: string,
|
value: string,
|
||||||
destination: string,
|
recipient: string,
|
||||||
) => {
|
) => {
|
||||||
// load add multisig form component
|
// load add multisig form component
|
||||||
TestUtils.Simulate.click(expandBalance)
|
fireEvent.click(sendButton)
|
||||||
// give time to re-render it
|
// give time to re-render it
|
||||||
await sleep(400)
|
await sleep(400)
|
||||||
|
|
||||||
const ethList = TestUtils.findRenderedDOMComponentWithClass(SafeDom, 'ETH')
|
// Fill first send funds screen
|
||||||
if (!ethList) throw new Error()
|
const recipientInput = SafeDom.getByPlaceholderText('Recipient*')
|
||||||
const ethButton = ethList.getElementsByTagName('button')
|
const amountInput = SafeDom.getByPlaceholderText('Amount*')
|
||||||
TestUtils.Simulate.click(ethButton[0])
|
const reviewBtn = SafeDom.getByTestId('review-tx-btn')
|
||||||
await sleep(450)
|
fireEvent.change(recipientInput, { target: { value: recipient } })
|
||||||
|
fireEvent.change(amountInput, { target: { value } })
|
||||||
|
await sleep(200)
|
||||||
|
fireEvent.click(reviewBtn)
|
||||||
|
|
||||||
// fill the form
|
// Submit the tx (Review Tx screen)
|
||||||
const inputs = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'input')
|
const submitBtn = SafeDom.getByTestId('submit-tx-btn')
|
||||||
const destinationInput = inputs[0]
|
fireEvent.click(submitBtn)
|
||||||
const amountInEthInput = inputs[1]
|
await sleep(1000)
|
||||||
TestUtils.Simulate.change(amountInEthInput, { target: { value } })
|
|
||||||
TestUtils.Simulate.change(destinationInput, { target: { value: destination } })
|
|
||||||
// $FlowFixMe
|
|
||||||
const form = TestUtils.findRenderedDOMComponentWithTag(SafeDom, 'form')
|
|
||||||
|
|
||||||
// submit it
|
|
||||||
TestUtils.Simulate.submit(form)
|
|
||||||
TestUtils.Simulate.submit(form)
|
|
||||||
|
|
||||||
return whenExecuted(SafeDom, SendToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const checkMinedMoveFundsTx = (Transaction: React.Component<any, any>, name: string) => {
|
|
||||||
checkMinedTx(Transaction, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const checkPendingMoveFundsTx = async (
|
|
||||||
Transaction: React.Component<any, any>,
|
|
||||||
safeThreshold: number,
|
|
||||||
name: string,
|
|
||||||
statusses: string[],
|
|
||||||
) => {
|
|
||||||
await checkPendingTx(Transaction, safeThreshold, name, statusses)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
// @flow
|
||||||
|
import { fireEvent } from '@testing-library/react'
|
||||||
|
import { sleep } from '~/utils/timer'
|
||||||
|
import { shortVersionOf } from '~/logic/wallets/ethAddresses'
|
||||||
|
import { TRANSACTIONS_TAB_BTN_TEST_ID } from '~/routes/safe/components/Layout'
|
||||||
|
import { TRANSACTION_ROW_TEST_ID } from '~/routes/safe/components/TransactionsNew/TxsTable'
|
||||||
|
import {
|
||||||
|
TRANSACTIONS_DESC_ADD_OWNER_TEST_ID,
|
||||||
|
TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID,
|
||||||
|
TRANSACTIONS_DESC_SEND_TEST_ID,
|
||||||
|
} from '~/routes/safe/components/TransactionsNew/TxsTable/ExpandedTx/TxDescription'
|
||||||
|
|
||||||
|
export const getLastTransaction = async (SafeDom: React.Component<any, any>) => {
|
||||||
|
// Travel to transactions
|
||||||
|
const transactionsBtn = SafeDom.getByTestId(TRANSACTIONS_TAB_BTN_TEST_ID)
|
||||||
|
fireEvent.click(transactionsBtn)
|
||||||
|
await sleep(200)
|
||||||
|
|
||||||
|
// Check the last transaction was registered
|
||||||
|
const transactionRows = SafeDom.getAllByTestId(TRANSACTION_ROW_TEST_ID)
|
||||||
|
expect(transactionRows.length).toBe(1)
|
||||||
|
fireEvent.click(transactionRows[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
export const checkRegisteredTxSend = async (
|
||||||
|
SafeDom: React.Component<any, any>,
|
||||||
|
ethAmount: number,
|
||||||
|
symbol: string,
|
||||||
|
ethAddress: string,
|
||||||
|
) => {
|
||||||
|
await getLastTransaction(SafeDom)
|
||||||
|
|
||||||
|
const txDescription = SafeDom.getAllByTestId(TRANSACTIONS_DESC_SEND_TEST_ID)[0]
|
||||||
|
expect(txDescription).toHaveTextContent(`Send ${ethAmount} ${symbol} to:${shortVersionOf(ethAddress, 4)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const checkRegisteredTxAddOwner = async (
|
||||||
|
SafeDom: React.Component<any, any>,
|
||||||
|
ownerAddress: string,
|
||||||
|
) => {
|
||||||
|
await getLastTransaction(SafeDom)
|
||||||
|
|
||||||
|
const txDescription = SafeDom.getAllByTestId(TRANSACTIONS_DESC_ADD_OWNER_TEST_ID)[0]
|
||||||
|
expect(txDescription).toHaveTextContent(`Add owner:${shortVersionOf(ownerAddress, 4)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const checkRegisteredTxRemoveOwner = async (
|
||||||
|
SafeDom: React.Component<any, any>,
|
||||||
|
ownerAddress: string,
|
||||||
|
) => {
|
||||||
|
await getLastTransaction(SafeDom)
|
||||||
|
|
||||||
|
const txDescription = SafeDom.getAllByTestId(TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID)[0]
|
||||||
|
expect(txDescription).toHaveTextContent(`Remove owner:${shortVersionOf(ownerAddress, 4)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const checkRegisteredTxReplaceOwner = async (
|
||||||
|
SafeDom: React.Component<any, any>,
|
||||||
|
oldOwnerAddress: string,
|
||||||
|
newOwnerAddress: string,
|
||||||
|
) => {
|
||||||
|
await getLastTransaction(SafeDom)
|
||||||
|
|
||||||
|
const txDescriptionRemove = SafeDom.getAllByTestId(TRANSACTIONS_DESC_REMOVE_OWNER_TEST_ID)[0]
|
||||||
|
expect(txDescriptionRemove).toHaveTextContent(`Remove owner:${shortVersionOf(oldOwnerAddress, 4)}`)
|
||||||
|
const txDescriptionAdd = SafeDom.getAllByTestId(TRANSACTIONS_DESC_ADD_OWNER_TEST_ID)[0]
|
||||||
|
expect(txDescriptionAdd).toHaveTextContent(`Add owner:${shortVersionOf(newOwnerAddress, 4)}`)
|
||||||
|
}
|
|
@ -7,17 +7,17 @@ export type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||||
|
|
||||||
export const getSize = (size: Size | typeof undefined) => {
|
export const getSize = (size: Size | typeof undefined) => {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 'xs':
|
case 'xs':
|
||||||
return xs
|
return xs
|
||||||
case 'sm':
|
case 'sm':
|
||||||
return sm
|
return sm
|
||||||
case 'md':
|
case 'md':
|
||||||
return md
|
return md
|
||||||
case 'lg':
|
case 'lg':
|
||||||
return lg
|
return lg
|
||||||
case 'xl':
|
case 'xl':
|
||||||
return xl
|
return xl
|
||||||
default:
|
default:
|
||||||
return '0px'
|
return '0px'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue