mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Refactor ConfirmTransaction to Functional Component (#17473)
* ConfirmTransaction: rm unused metricEvent context * ConfirmTransaction: rm unused mapToProps props: - unapprovedTxs - id * ConfirmTransaction: convert to FC * ConfirmTransaction: use const ORIGIN_METAMASK * ConfirmTransaction: rm mapStateToProps * ConfirmTransaction: mv confirm-transaction ducks * ConfirmTransaction: mv getContractMethodData duck * ConfirmTransaction: rm container file * ConfirmTransaction: use ORIGIN_METAMASK const * ConfirmationTransaction: add tests * ConfirmTransaction: update jest mock after merge * tests: update snapshot after mock-state updates
This commit is contained in:
parent
92367dff79
commit
b5c1de900d
@ -140,12 +140,14 @@
|
|||||||
"incomingTransactions": {},
|
"incomingTransactions": {},
|
||||||
"unapprovedTxs": {
|
"unapprovedTxs": {
|
||||||
"8393540981007587": {
|
"8393540981007587": {
|
||||||
|
"chainId": "0x5",
|
||||||
"id": 8393540981007587,
|
"id": 8393540981007587,
|
||||||
"time": 1536268017676,
|
"time": 1536268017676,
|
||||||
"status": "unapproved",
|
"status": "unapproved",
|
||||||
"metamaskNetworkId": "4",
|
"metamaskNetworkId": "4",
|
||||||
"loadingDefaults": false,
|
"loadingDefaults": false,
|
||||||
"txParams": {
|
"txParams": {
|
||||||
|
"data": "0xa9059cbb000000000000000000000000b19ac54efa18cc3a14a5b821bfec73d284bf0c5e0000000000000000000000000000000000000000000000003782dace9d900000",
|
||||||
"from": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
|
"from": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
|
||||||
"to": "0xc42edfcc21ed14dda456aa0756c153f7985d8813",
|
"to": "0xc42edfcc21ed14dda456aa0756c153f7985d8813",
|
||||||
"value": "0x0",
|
"value": "0x0",
|
||||||
@ -185,7 +187,7 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"origin": "MetaMask"
|
"origin": "metamask"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
|
"selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
|
||||||
|
@ -44,7 +44,7 @@ exports[`SignatureRequestOriginal should match snapshot 1`] = `
|
|||||||
|
|
||||||
of
|
of
|
||||||
|
|
||||||
0
|
1
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="confirm-page-container-navigation__longtext"
|
class="confirm-page-container-navigation__longtext"
|
||||||
@ -54,7 +54,7 @@ exports[`SignatureRequestOriginal should match snapshot 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="confirm-page-container-navigation__container"
|
class="confirm-page-container-navigation__container"
|
||||||
style="visibility: hidden;"
|
style="visibility: initial;"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="confirm-page-container-navigation__arrow"
|
class="confirm-page-container-navigation__arrow"
|
||||||
|
@ -41,7 +41,7 @@ exports[`Signature Request Component render should match snapshot 1`] = `
|
|||||||
|
|
||||||
of
|
of
|
||||||
|
|
||||||
0
|
1
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="confirm-page-container-navigation__longtext"
|
class="confirm-page-container-navigation__longtext"
|
||||||
@ -51,7 +51,7 @@ exports[`Signature Request Component render should match snapshot 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="confirm-page-container-navigation__container"
|
class="confirm-page-container-navigation__container"
|
||||||
style="visibility: hidden;"
|
style="visibility: initial;"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="confirm-page-container-navigation__arrow"
|
class="confirm-page-container-navigation__arrow"
|
||||||
|
@ -0,0 +1,279 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Confirmation Transaction Page should display the Loading component when the transaction is invalid 1`] = `
|
||||||
|
<div
|
||||||
|
class="loading-overlay"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="loading-overlay__container"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="spinner loading-overlay__spinner"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="lds-spinner"
|
||||||
|
height="100%"
|
||||||
|
preserveAspectRatio="xMidYMid"
|
||||||
|
style="background: none;"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
width="100%"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
transform="rotate(0 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.9166666666666666s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(30 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.8333333333333334s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(60 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.75s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(90 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.6666666666666666s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(120 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.5833333333333334s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(150 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.5s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(180 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.4166666666666667s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(210 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.3333333333333333s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(240 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.25s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(270 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.16666666666666666s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(300 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="-0.08333333333333333s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(330 50 50)"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="var(--color-warning-default)"
|
||||||
|
height="30"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
width="10"
|
||||||
|
x="45"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="opacity"
|
||||||
|
begin="0s"
|
||||||
|
dur="1s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
values="1;0"
|
||||||
|
/>
|
||||||
|
</rect>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -1,6 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { Switch, Route } from 'react-router-dom';
|
import { Switch, Route, useHistory, useParams } from 'react-router-dom';
|
||||||
import Loading from '../../components/ui/loading-screen';
|
import Loading from '../../components/ui/loading-screen';
|
||||||
import ConfirmTransactionSwitch from '../confirm-transaction-switch';
|
import ConfirmTransactionSwitch from '../confirm-transaction-switch';
|
||||||
import ConfirmContractInteraction from '../confirm-contract-interaction';
|
import ConfirmContractInteraction from '../confirm-contract-interaction';
|
||||||
@ -9,6 +9,14 @@ import ConfirmDeployContract from '../confirm-deploy-contract';
|
|||||||
import ConfirmDecryptMessage from '../confirm-decrypt-message';
|
import ConfirmDecryptMessage from '../confirm-decrypt-message';
|
||||||
import ConfirmEncryptionPublicKey from '../confirm-encryption-public-key';
|
import ConfirmEncryptionPublicKey from '../confirm-encryption-public-key';
|
||||||
|
|
||||||
|
import { ORIGIN_METAMASK } from '../../../shared/constants/app';
|
||||||
|
|
||||||
|
import {
|
||||||
|
clearConfirmTransaction,
|
||||||
|
setTransactionToConfirm,
|
||||||
|
} from '../../ducks/confirm-transaction/confirm-transaction.duck';
|
||||||
|
import { getMostRecentOverviewPage } from '../../ducks/history/history';
|
||||||
|
import { getSendTo } from '../../ducks/send';
|
||||||
import {
|
import {
|
||||||
CONFIRM_TRANSACTION_ROUTE,
|
CONFIRM_TRANSACTION_ROUTE,
|
||||||
CONFIRM_DEPLOY_CONTRACT_PATH,
|
CONFIRM_DEPLOY_CONTRACT_PATH,
|
||||||
@ -19,188 +27,191 @@ import {
|
|||||||
ENCRYPTION_PUBLIC_KEY_REQUEST_PATH,
|
ENCRYPTION_PUBLIC_KEY_REQUEST_PATH,
|
||||||
DEFAULT_ROUTE,
|
DEFAULT_ROUTE,
|
||||||
} from '../../helpers/constants/routes';
|
} from '../../helpers/constants/routes';
|
||||||
|
import { isTokenMethodAction } from '../../helpers/utils/transactions.util';
|
||||||
|
import { usePrevious } from '../../hooks/usePrevious';
|
||||||
|
import {
|
||||||
|
getUnapprovedTransactions,
|
||||||
|
unconfirmedTransactionsListSelector,
|
||||||
|
unconfirmedTransactionsHashSelector,
|
||||||
|
} from '../../selectors';
|
||||||
import {
|
import {
|
||||||
disconnectGasFeeEstimatePoller,
|
disconnectGasFeeEstimatePoller,
|
||||||
|
getContractMethodData,
|
||||||
getGasFeeEstimatesAndStartPolling,
|
getGasFeeEstimatesAndStartPolling,
|
||||||
addPollingTokenToAppState,
|
addPollingTokenToAppState,
|
||||||
removePollingTokenFromAppState,
|
removePollingTokenFromAppState,
|
||||||
|
setDefaultHomeActiveTabName,
|
||||||
} from '../../store/actions';
|
} from '../../store/actions';
|
||||||
import ConfirmSignatureRequest from '../confirm-signature-request';
|
import ConfirmSignatureRequest from '../confirm-signature-request';
|
||||||
import ConfirmTokenTransactionSwitch from './confirm-token-transaction-switch';
|
import ConfirmTokenTransactionSwitch from './confirm-token-transaction-switch';
|
||||||
|
|
||||||
export default class ConfirmTransaction extends Component {
|
const ConfirmTransaction = () => {
|
||||||
static contextTypes = {
|
const dispatch = useDispatch();
|
||||||
metricsEvent: PropTypes.func,
|
const history = useHistory();
|
||||||
};
|
const { id: paramsTransactionId } = useParams();
|
||||||
|
|
||||||
static propTypes = {
|
const [isMounted, setIsMounted] = useState(false);
|
||||||
history: PropTypes.object.isRequired,
|
const [pollingToken, setPollingToken] = useState();
|
||||||
totalUnapprovedCount: PropTypes.number.isRequired,
|
|
||||||
sendTo: PropTypes.string,
|
|
||||||
setTransactionToConfirm: PropTypes.func,
|
|
||||||
clearConfirmTransaction: PropTypes.func,
|
|
||||||
mostRecentOverviewPage: PropTypes.string.isRequired,
|
|
||||||
transaction: PropTypes.object,
|
|
||||||
getContractMethodData: PropTypes.func,
|
|
||||||
transactionId: PropTypes.string,
|
|
||||||
paramsTransactionId: PropTypes.string,
|
|
||||||
isTokenMethodAction: PropTypes.bool,
|
|
||||||
setDefaultHomeActiveTabName: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage);
|
||||||
super(props);
|
const sendTo = useSelector(getSendTo);
|
||||||
this.state = {};
|
const unapprovedTxs = useSelector(getUnapprovedTransactions);
|
||||||
}
|
const unconfirmedTransactions = useSelector(
|
||||||
|
unconfirmedTransactionsListSelector,
|
||||||
|
);
|
||||||
|
const unconfirmedMessages = useSelector(unconfirmedTransactionsHashSelector);
|
||||||
|
|
||||||
_beforeUnload = () => {
|
const totalUnapprovedCount = unconfirmedTransactions.length || 0;
|
||||||
this._isMounted = false;
|
const transaction = useMemo(() => {
|
||||||
if (this.state.pollingToken) {
|
return totalUnapprovedCount
|
||||||
disconnectGasFeeEstimatePoller(this.state.pollingToken);
|
? unapprovedTxs[paramsTransactionId] ||
|
||||||
removePollingTokenFromAppState(this.state.pollingToken);
|
unconfirmedMessages[paramsTransactionId] ||
|
||||||
|
unconfirmedTransactions[0]
|
||||||
|
: {};
|
||||||
|
}, [
|
||||||
|
paramsTransactionId,
|
||||||
|
totalUnapprovedCount,
|
||||||
|
unapprovedTxs,
|
||||||
|
unconfirmedMessages,
|
||||||
|
unconfirmedTransactions,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const { id, type } = transaction;
|
||||||
|
const transactionId = id && String(id);
|
||||||
|
const isValidERC20TokenMethod = isTokenMethodAction(type);
|
||||||
|
|
||||||
|
const prevParamsTransactionId = usePrevious(paramsTransactionId);
|
||||||
|
const prevTransactionId = usePrevious(transactionId);
|
||||||
|
|
||||||
|
const _beforeUnload = useCallback(() => {
|
||||||
|
setIsMounted(false);
|
||||||
|
|
||||||
|
if (pollingToken) {
|
||||||
|
disconnectGasFeeEstimatePoller(pollingToken);
|
||||||
|
removePollingTokenFromAppState(pollingToken);
|
||||||
}
|
}
|
||||||
};
|
}, [pollingToken]);
|
||||||
|
|
||||||
componentDidMount() {
|
useEffect(() => {
|
||||||
this._isMounted = true;
|
setIsMounted(true);
|
||||||
const {
|
|
||||||
totalUnapprovedCount = 0,
|
|
||||||
sendTo,
|
|
||||||
history,
|
|
||||||
mostRecentOverviewPage,
|
|
||||||
transaction: { txParams: { data } = {}, origin } = {},
|
|
||||||
getContractMethodData,
|
|
||||||
transactionId,
|
|
||||||
paramsTransactionId,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
getGasFeeEstimatesAndStartPolling().then((pollingToken) => {
|
const { txParams: { data } = {}, origin } = transaction;
|
||||||
if (this._isMounted) {
|
|
||||||
this.setState({ pollingToken });
|
getGasFeeEstimatesAndStartPolling().then((_pollingToken) => {
|
||||||
addPollingTokenToAppState(pollingToken);
|
if (isMounted) {
|
||||||
|
setPollingToken(_pollingToken);
|
||||||
|
addPollingTokenToAppState(_pollingToken);
|
||||||
} else {
|
} else {
|
||||||
disconnectGasFeeEstimatePoller(pollingToken);
|
disconnectGasFeeEstimatePoller(_pollingToken);
|
||||||
removePollingTokenFromAppState(pollingToken);
|
removePollingTokenFromAppState(_pollingToken);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('beforeunload', this._beforeUnload);
|
window.addEventListener('beforeunload', _beforeUnload);
|
||||||
|
|
||||||
if (!totalUnapprovedCount && !sendTo) {
|
if (!totalUnapprovedCount && !sendTo) {
|
||||||
history.replace(mostRecentOverviewPage);
|
history.replace(mostRecentOverviewPage);
|
||||||
return;
|
} else {
|
||||||
|
if (origin !== ORIGIN_METAMASK) {
|
||||||
|
dispatch(getContractMethodData(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
const txId = transactionId || paramsTransactionId;
|
||||||
|
if (txId) {
|
||||||
|
dispatch(setTransactionToConfirm(txId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (origin !== 'metamask') {
|
return () => {
|
||||||
getContractMethodData(data);
|
_beforeUnload();
|
||||||
}
|
window.removeEventListener('beforeunload', _beforeUnload);
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
const txId = transactionId || paramsTransactionId;
|
useEffect(() => {
|
||||||
if (txId) {
|
const { txData: { txParams: { data } = {}, origin } = {} } = transaction;
|
||||||
this.props.setTransactionToConfirm(txId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this._beforeUnload();
|
|
||||||
window.removeEventListener('beforeunload', this._beforeUnload);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
const {
|
|
||||||
setTransactionToConfirm,
|
|
||||||
transaction: { txData: { txParams: { data } = {}, origin } = {} },
|
|
||||||
clearConfirmTransaction,
|
|
||||||
getContractMethodData,
|
|
||||||
paramsTransactionId,
|
|
||||||
transactionId,
|
|
||||||
history,
|
|
||||||
mostRecentOverviewPage,
|
|
||||||
totalUnapprovedCount,
|
|
||||||
setDefaultHomeActiveTabName,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
paramsTransactionId &&
|
paramsTransactionId &&
|
||||||
transactionId &&
|
transactionId &&
|
||||||
prevProps.paramsTransactionId !== paramsTransactionId
|
prevParamsTransactionId !== paramsTransactionId
|
||||||
) {
|
) {
|
||||||
clearConfirmTransaction();
|
dispatch(clearConfirmTransaction());
|
||||||
setTransactionToConfirm(paramsTransactionId);
|
dispatch(setTransactionToConfirm(paramsTransactionId));
|
||||||
if (origin !== 'metamask') {
|
if (origin !== ORIGIN_METAMASK) {
|
||||||
getContractMethodData(data);
|
dispatch(getContractMethodData(data));
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (prevTransactionId && !transactionId && !totalUnapprovedCount) {
|
||||||
prevProps.transactionId &&
|
dispatch(setDefaultHomeActiveTabName('activity')).then(() => {
|
||||||
!transactionId &&
|
|
||||||
!totalUnapprovedCount
|
|
||||||
) {
|
|
||||||
setDefaultHomeActiveTabName('activity').then(() => {
|
|
||||||
history.replace(DEFAULT_ROUTE);
|
history.replace(DEFAULT_ROUTE);
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
prevProps.transactionId &&
|
prevTransactionId &&
|
||||||
transactionId &&
|
transactionId &&
|
||||||
prevProps.transactionId !== transactionId
|
prevTransactionId !== transactionId
|
||||||
) {
|
) {
|
||||||
history.replace(mostRecentOverviewPage);
|
history.replace(mostRecentOverviewPage);
|
||||||
}
|
}
|
||||||
|
}, [
|
||||||
|
dispatch,
|
||||||
|
transaction,
|
||||||
|
paramsTransactionId,
|
||||||
|
transactionId,
|
||||||
|
history,
|
||||||
|
mostRecentOverviewPage,
|
||||||
|
prevParamsTransactionId,
|
||||||
|
prevTransactionId,
|
||||||
|
totalUnapprovedCount,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const validTransactionId =
|
||||||
|
transactionId &&
|
||||||
|
(!paramsTransactionId || paramsTransactionId === transactionId);
|
||||||
|
|
||||||
|
if (isValidERC20TokenMethod && validTransactionId) {
|
||||||
|
return <ConfirmTokenTransactionSwitch transaction={transaction} />;
|
||||||
}
|
}
|
||||||
|
// Show routes when state.confirmTransaction has been set and when either the ID in the params
|
||||||
|
// isn't specified or is specified and matches the ID in state.confirmTransaction in order to
|
||||||
|
// support URLs of /confirm-transaction or /confirm-transaction/<transactionId>
|
||||||
|
return validTransactionId ? (
|
||||||
|
<Switch>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${CONFIRM_DEPLOY_CONTRACT_PATH}`}
|
||||||
|
component={ConfirmDeployContract}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${CONFIRM_SEND_ETHER_PATH}`}
|
||||||
|
component={ConfirmSendEther}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${CONFIRM_TOKEN_METHOD_PATH}`}
|
||||||
|
component={ConfirmContractInteraction}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${SIGNATURE_REQUEST_PATH}`}
|
||||||
|
component={ConfirmSignatureRequest}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${DECRYPT_MESSAGE_REQUEST_PATH}`}
|
||||||
|
component={ConfirmDecryptMessage}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${ENCRYPTION_PUBLIC_KEY_REQUEST_PATH}`}
|
||||||
|
component={ConfirmEncryptionPublicKey}
|
||||||
|
/>
|
||||||
|
<Route path="*" component={ConfirmTransactionSwitch} />
|
||||||
|
</Switch>
|
||||||
|
) : (
|
||||||
|
<Loading />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
export default ConfirmTransaction;
|
||||||
const {
|
|
||||||
transactionId,
|
|
||||||
paramsTransactionId,
|
|
||||||
isTokenMethodAction,
|
|
||||||
transaction,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const validTransactionId =
|
|
||||||
transactionId &&
|
|
||||||
(!paramsTransactionId || paramsTransactionId === transactionId);
|
|
||||||
|
|
||||||
if (isTokenMethodAction && validTransactionId) {
|
|
||||||
return <ConfirmTokenTransactionSwitch transaction={transaction} />;
|
|
||||||
}
|
|
||||||
// Show routes when state.confirmTransaction has been set and when either the ID in the params
|
|
||||||
// isn't specified or is specified and matches the ID in state.confirmTransaction in order to
|
|
||||||
// support URLs of /confirm-transaction or /confirm-transaction/<transactionId>
|
|
||||||
return validTransactionId ? (
|
|
||||||
<Switch>
|
|
||||||
<Route
|
|
||||||
exact
|
|
||||||
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${CONFIRM_DEPLOY_CONTRACT_PATH}`}
|
|
||||||
component={ConfirmDeployContract}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
exact
|
|
||||||
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${CONFIRM_SEND_ETHER_PATH}`}
|
|
||||||
component={ConfirmSendEther}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
exact
|
|
||||||
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${CONFIRM_TOKEN_METHOD_PATH}`}
|
|
||||||
component={ConfirmContractInteraction}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
exact
|
|
||||||
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${SIGNATURE_REQUEST_PATH}`}
|
|
||||||
component={ConfirmSignatureRequest}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
exact
|
|
||||||
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${DECRYPT_MESSAGE_REQUEST_PATH}`}
|
|
||||||
component={ConfirmDecryptMessage}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
exact
|
|
||||||
path={`${CONFIRM_TRANSACTION_ROUTE}/:id?${ENCRYPTION_PUBLIC_KEY_REQUEST_PATH}`}
|
|
||||||
component={ConfirmEncryptionPublicKey}
|
|
||||||
/>
|
|
||||||
<Route path="*" component={ConfirmTransactionSwitch} />
|
|
||||||
</Switch>
|
|
||||||
) : (
|
|
||||||
<Loading />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
import { connect } from 'react-redux';
|
|
||||||
import { compose } from 'redux';
|
|
||||||
import { withRouter } from 'react-router-dom';
|
|
||||||
import {
|
|
||||||
setTransactionToConfirm,
|
|
||||||
clearConfirmTransaction,
|
|
||||||
} from '../../ducks/confirm-transaction/confirm-transaction.duck';
|
|
||||||
import { isTokenMethodAction } from '../../helpers/utils/transactions.util';
|
|
||||||
|
|
||||||
import {
|
|
||||||
getContractMethodData,
|
|
||||||
setDefaultHomeActiveTabName,
|
|
||||||
} from '../../store/actions';
|
|
||||||
import {
|
|
||||||
unconfirmedTransactionsListSelector,
|
|
||||||
unconfirmedTransactionsHashSelector,
|
|
||||||
} from '../../selectors';
|
|
||||||
import { getMostRecentOverviewPage } from '../../ducks/history/history';
|
|
||||||
import { getSendTo } from '../../ducks/send';
|
|
||||||
import ConfirmTransaction from './confirm-transaction.component';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => {
|
|
||||||
const {
|
|
||||||
metamask: { unapprovedTxs },
|
|
||||||
} = state;
|
|
||||||
const {
|
|
||||||
match: { params = {} },
|
|
||||||
} = ownProps;
|
|
||||||
const { id } = params;
|
|
||||||
const sendTo = getSendTo(state);
|
|
||||||
|
|
||||||
const unconfirmedTransactions = unconfirmedTransactionsListSelector(state);
|
|
||||||
const unconfirmedMessages = unconfirmedTransactionsHashSelector(state);
|
|
||||||
const totalUnconfirmed = unconfirmedTransactions.length;
|
|
||||||
const transaction = totalUnconfirmed
|
|
||||||
? unapprovedTxs[id] || unconfirmedMessages[id] || unconfirmedTransactions[0]
|
|
||||||
: {};
|
|
||||||
const { id: transactionId, type } = transaction;
|
|
||||||
|
|
||||||
return {
|
|
||||||
totalUnapprovedCount: totalUnconfirmed,
|
|
||||||
sendTo,
|
|
||||||
unapprovedTxs,
|
|
||||||
id,
|
|
||||||
mostRecentOverviewPage: getMostRecentOverviewPage(state),
|
|
||||||
paramsTransactionId: id && String(id),
|
|
||||||
transactionId: transactionId && String(transactionId),
|
|
||||||
transaction,
|
|
||||||
isTokenMethodAction: isTokenMethodAction(type),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
|
||||||
return {
|
|
||||||
setTransactionToConfirm: (transactionId) => {
|
|
||||||
dispatch(setTransactionToConfirm(transactionId));
|
|
||||||
},
|
|
||||||
clearConfirmTransaction: () => dispatch(clearConfirmTransaction()),
|
|
||||||
getContractMethodData: (data) => dispatch(getContractMethodData(data)),
|
|
||||||
setDefaultHomeActiveTabName: (tabName) =>
|
|
||||||
dispatch(setDefaultHomeActiveTabName(tabName)),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withRouter,
|
|
||||||
connect(mapStateToProps, mapDispatchToProps),
|
|
||||||
)(ConfirmTransaction);
|
|
290
ui/pages/confirm-transaction/confirm-transaction.test.js
Normal file
290
ui/pages/confirm-transaction/confirm-transaction.test.js
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import configureMockStore from 'redux-mock-store';
|
||||||
|
import thunk from 'redux-thunk';
|
||||||
|
|
||||||
|
import ReactRouterDOM from 'react-router-dom';
|
||||||
|
|
||||||
|
import * as ConfirmTransactionDucks from '../../ducks/confirm-transaction/confirm-transaction.duck';
|
||||||
|
import * as Actions from '../../store/actions';
|
||||||
|
import _mockState from '../../../test/data/mock-state.json';
|
||||||
|
import { renderWithProvider } from '../../../test/lib/render-helpers';
|
||||||
|
import { setBackgroundConnection } from '../../../test/jest';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CONFIRM_TRANSACTION_ROUTE,
|
||||||
|
CONFIRM_DEPLOY_CONTRACT_PATH,
|
||||||
|
CONFIRM_SEND_ETHER_PATH,
|
||||||
|
CONFIRM_TOKEN_METHOD_PATH,
|
||||||
|
SIGNATURE_REQUEST_PATH,
|
||||||
|
DECRYPT_MESSAGE_REQUEST_PATH,
|
||||||
|
ENCRYPTION_PUBLIC_KEY_REQUEST_PATH,
|
||||||
|
} from '../../helpers/constants/routes';
|
||||||
|
|
||||||
|
import ConfirmTransaction from '.';
|
||||||
|
|
||||||
|
const mockUnapprovedTx = Object.values(_mockState.metamask.unapprovedTxs)[0];
|
||||||
|
|
||||||
|
const middleware = [thunk];
|
||||||
|
|
||||||
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
..._mockState.metamask,
|
||||||
|
},
|
||||||
|
appState: {
|
||||||
|
gasLoadingAnimationIsShowing: false,
|
||||||
|
},
|
||||||
|
history: {
|
||||||
|
mostRecentOverviewPage: '/',
|
||||||
|
},
|
||||||
|
send: {
|
||||||
|
draftTransactions: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
setBackgroundConnection({
|
||||||
|
addPollingTokenToAppState: jest.fn(),
|
||||||
|
disconnectGasFeeEstimatePoller: jest.fn(),
|
||||||
|
getContractMethodData: jest.fn(),
|
||||||
|
getGasFeeEstimatesAndStartPolling: jest.fn(),
|
||||||
|
removePollingTokenFromAppState: jest.fn(),
|
||||||
|
setDefaultHomeActiveTabName: jest.fn(),
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.mock('../../ducks/confirm-transaction/confirm-transaction.duck', () => ({
|
||||||
|
setTransactionToConfirm: jest.fn().mockImplementation((txId) => {
|
||||||
|
return { type: 'mock-set-transaction-to-confirm', value: txId };
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('react-router-dom', () => {
|
||||||
|
const original = jest.requireActual('react-router-dom');
|
||||||
|
return {
|
||||||
|
...original,
|
||||||
|
useHistory: () => ({
|
||||||
|
replace: jest.fn(),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.mock('../confirm-contract-interaction', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: () => {
|
||||||
|
return <div className="mock-confirm-contract-interaction" />;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('../confirm-decrypt-message', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: () => {
|
||||||
|
return <div className="mock-confirm-decrypt-message" />;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('../confirm-deploy-contract', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: () => {
|
||||||
|
return <div className="mock-confirm-deploy-contract" />;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('../confirm-encryption-public-key', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: () => {
|
||||||
|
return <div className="mock-confirm-encryption-public-key" />;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('../confirm-send-ether', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: () => {
|
||||||
|
return <div className="mock-confirm-send-ether" />;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('../confirm-signature-request', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: () => {
|
||||||
|
return <div className="mock-confirm-signature-request" />;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('./confirm-token-transaction-switch', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: () => {
|
||||||
|
return <div className="mock-confirm-token-transaction-switch" />;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('../confirm-transaction-switch', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: () => {
|
||||||
|
return <div className="mock-confirm-transaction-switch" />;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Confirmation Transaction Page', () => {
|
||||||
|
it('should display the Loading component when the transaction is invalid', () => {
|
||||||
|
const mockStore = configureMockStore(middleware)({
|
||||||
|
...mockState,
|
||||||
|
metamask: {
|
||||||
|
...mockState.metamask,
|
||||||
|
unapprovedTxs: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { container } = renderWithProvider(<ConfirmTransaction />, mockStore);
|
||||||
|
|
||||||
|
expect(container.querySelector('.loading-overlay')).toBeInTheDocument();
|
||||||
|
expect(container.querySelector('.loading-overlay')).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display the Loading component when the transaction is valid', () => {
|
||||||
|
const mockStore = configureMockStore(middleware)({ ...mockState });
|
||||||
|
const { container } = renderWithProvider(<ConfirmTransaction />, mockStore);
|
||||||
|
expect(container.querySelector('.loading-overlay')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
[
|
||||||
|
[CONFIRM_DEPLOY_CONTRACT_PATH, '.mock-confirm-deploy-contract'],
|
||||||
|
[CONFIRM_SEND_ETHER_PATH, '.mock-confirm-send-ether'],
|
||||||
|
[CONFIRM_TOKEN_METHOD_PATH, '.mock-confirm-contract-interaction'],
|
||||||
|
[DECRYPT_MESSAGE_REQUEST_PATH, '.mock-confirm-decrypt-message'],
|
||||||
|
[ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, '.mock-confirm-encryption-public-key'],
|
||||||
|
[SIGNATURE_REQUEST_PATH, '.mock-confirm-signature-request'],
|
||||||
|
].forEach(([componentPath, mockClassNameMatch]) => {
|
||||||
|
it(`should render "${componentPath}" route`, () => {
|
||||||
|
const mockStore = configureMockStore(middleware)(mockState);
|
||||||
|
const { container } = renderWithProvider(
|
||||||
|
<ConfirmTransaction />,
|
||||||
|
mockStore,
|
||||||
|
`${CONFIRM_TRANSACTION_ROUTE}/${mockUnapprovedTx.id}${componentPath}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container.querySelector(mockClassNameMatch)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should render ConfirmTokenTransactionSwitch component if it's a valid ERC20 token method`, () => {
|
||||||
|
const mockStore = configureMockStore(middleware)({
|
||||||
|
...mockState,
|
||||||
|
metamask: {
|
||||||
|
...mockState.metamask,
|
||||||
|
unapprovedTxs: {
|
||||||
|
[mockUnapprovedTx.id]: {
|
||||||
|
...mockUnapprovedTx,
|
||||||
|
type: 'transfer',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { container } = renderWithProvider(
|
||||||
|
<ConfirmTransaction />,
|
||||||
|
mockStore,
|
||||||
|
// use valid matched route path to check against ConfirmTokenTransactionSwitch
|
||||||
|
`${CONFIRM_TRANSACTION_ROUTE}/${mockUnapprovedTx.id}${CONFIRM_DEPLOY_CONTRACT_PATH}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
container.querySelector('.mock-confirm-token-transaction-switch'),
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should render ConfirmTransactionSwitch component if the route path is unmatched and the transaction is valid`, () => {
|
||||||
|
const mockStore = configureMockStore(middleware)(mockState);
|
||||||
|
const { container } = renderWithProvider(
|
||||||
|
<ConfirmTransaction />,
|
||||||
|
mockStore,
|
||||||
|
`/unknown-path`,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
container.querySelector('.mock-confirm-transaction-switch'),
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('initialization', () => {
|
||||||
|
it('should poll for gas estimates', () => {
|
||||||
|
const mockStore = configureMockStore(middleware)(mockState);
|
||||||
|
const gasEstimationPollingSpy = jest.spyOn(
|
||||||
|
Actions,
|
||||||
|
'getGasFeeEstimatesAndStartPolling',
|
||||||
|
);
|
||||||
|
|
||||||
|
renderWithProvider(<ConfirmTransaction />, mockStore);
|
||||||
|
|
||||||
|
expect(gasEstimationPollingSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call setTransactionToConfirm if transaction id is provided', () => {
|
||||||
|
const mockStore = configureMockStore(middleware)({ ...mockState });
|
||||||
|
ConfirmTransactionDucks.setTransactionToConfirm.mockClear();
|
||||||
|
|
||||||
|
renderWithProvider(<ConfirmTransaction />, mockStore);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
ConfirmTransactionDucks.setTransactionToConfirm,
|
||||||
|
).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not call setTransactionToConfirm when transaction id is not provided', () => {
|
||||||
|
const mockStore = configureMockStore(middleware)({
|
||||||
|
...mockState,
|
||||||
|
metamask: { ...mockState.metamask, unapprovedTxs: {} },
|
||||||
|
});
|
||||||
|
jest.spyOn(ReactRouterDOM, 'useParams').mockImplementation(() => {
|
||||||
|
return { id: null };
|
||||||
|
});
|
||||||
|
ConfirmTransactionDucks.setTransactionToConfirm.mockClear();
|
||||||
|
|
||||||
|
renderWithProvider(<ConfirmTransaction />, mockStore);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
ConfirmTransactionDucks.setTransactionToConfirm,
|
||||||
|
).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when unapproved transactions exist or a sendTo recipient exists', () => {
|
||||||
|
it('should not call history.replace(mostRecentOverviewPage)', () => {
|
||||||
|
const mockStore = configureMockStore(middleware)(mockState);
|
||||||
|
const replaceSpy = jest.fn();
|
||||||
|
jest.spyOn(ReactRouterDOM, 'useHistory').mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
replace: replaceSpy,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
renderWithProvider(<ConfirmTransaction />, mockStore);
|
||||||
|
expect(replaceSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when no unapproved transactions and no sendTo recipient exist', () => {
|
||||||
|
it('should call history.replace(mostRecentOverviewPage)', () => {
|
||||||
|
const mockStore = configureMockStore(middleware)({
|
||||||
|
...mockState,
|
||||||
|
metamask: {
|
||||||
|
...mockState.metamask,
|
||||||
|
unapprovedTxs: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const replaceSpy = jest.fn();
|
||||||
|
jest.spyOn(ReactRouterDOM, 'useHistory').mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
replace: replaceSpy,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
renderWithProvider(<ConfirmTransaction />, mockStore, '/asdfb');
|
||||||
|
expect(replaceSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,3 +1,3 @@
|
|||||||
import ConfirmTransaction from './confirm-transaction.container';
|
import ConfirmTransaction from './confirm-transaction.component';
|
||||||
|
|
||||||
export default ConfirmTransaction;
|
export default ConfirmTransaction;
|
||||||
|
Loading…
Reference in New Issue
Block a user