From 0e0e7ac8309c1b8f8be80624ebaa194dcc520cea Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Mon, 29 Nov 2021 21:38:24 +0530 Subject: [PATCH] Legacy transactions to use old transaction flow (#12782) --- test/data/mock-estimates.json | 27 ++++ ...onfirm-page-container-content.component.js | 19 +-- ...m-page-container-content.component.test.js | 2 + ...onfirm-page-container-summary.component.js | 8 +- .../confirm-page-container.component.js | 22 ++-- .../app/gas-timing/gas-timing.component.js | 14 +-- .../transaction-detail.component.js | 6 +- .../transaction-detail.component.test.js | 35 ++++-- ui/hooks/gasFeeInput/useGasFeeInputs.js | 5 + ui/hooks/gasFeeInput/useGasFeeInputs.test.js | 34 ++++++ .../confirm-transaction-base.component.js | 32 +++-- .../gas-details-item/gas-details-item.js | 8 +- .../gas-details-item/gas-details-item.test.js | 23 ++-- .../transaction-alerts/transaction-alerts.js | 9 +- .../transaction-alerts.test.js | 115 ++++++++++++++---- 15 files changed, 264 insertions(+), 95 deletions(-) create mode 100644 test/data/mock-estimates.json diff --git a/test/data/mock-estimates.json b/test/data/mock-estimates.json new file mode 100644 index 000000000..8f7587f92 --- /dev/null +++ b/test/data/mock-estimates.json @@ -0,0 +1,27 @@ +{ + "fee-market": { + "gasEstimateType": "fee-market", + "gasFeeEstimates": { + "low": { + "minWaitTimeEstimate": 180000, + "maxWaitTimeEstimate": 300000, + "suggestedMaxPriorityFeePerGas": "3", + "suggestedMaxFeePerGas": "53" + }, + "medium": { + "minWaitTimeEstimate": 15000, + "maxWaitTimeEstimate": 60000, + "suggestedMaxPriorityFeePerGas": "7", + "suggestedMaxFeePerGas": "70" + }, + "high": { + "minWaitTimeEstimate": 0, + "maxWaitTimeEstimate": 15000, + "suggestedMaxPriorityFeePerGas": "10", + "suggestedMaxFeePerGas": "100" + }, + "estimatedBaseFee": "50" + }, + "estimatedGasFeeTimeBounds": {} + } +} diff --git a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index 8e4da74b9..069d58da1 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -7,9 +7,6 @@ import ActionableMessage from '../../../ui/actionable-message/actionable-message import { PageContainerFooter } from '../../../ui/page-container'; import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.'; -// eslint-disable-next-line prefer-destructuring -const EIP_1559_V2 = process.env.EIP_1559_V2; - export default class ConfirmPageContainerContent extends Component { static contextTypes = { t: PropTypes.func.isRequired, @@ -42,7 +39,8 @@ export default class ConfirmPageContainerContent extends Component { hideUserAcknowledgedGasMissing: PropTypes.bool, unapprovedTxCount: PropTypes.number, rejectNText: PropTypes.string, - hideTitle: PropTypes.boolean, + hideTitle: PropTypes.bool, + supportsEIP1559V2: PropTypes.bool, }; renderContent() { @@ -101,6 +99,7 @@ export default class ConfirmPageContainerContent extends Component { hideTitle, setUserAcknowledgedGasMissing, hideUserAcknowledgedGasMissing, + supportsEIP1559V2, } = this.props; const primaryAction = hideUserAcknowledgedGasMissing @@ -141,11 +140,13 @@ export default class ConfirmPageContainerContent extends Component { hideTitle={hideTitle} /> {this.renderContent()} - {!EIP_1559_V2 && !hasSimulationError && (errorKey || errorMessage) && ( -
- -
- )} + {!supportsEIP1559V2 && + !hasSimulationError && + (errorKey || errorMessage) && ( +
+ +
+ )} { }); it('render ConfirmPageContainer component with simulation error', async () => { + process.env.EIP_1559_V2 = false; + const { queryByText, getByText } = renderWithProvider( , store, diff --git a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js index 58ee67d0c..05a5964fd 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js @@ -3,9 +3,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import Identicon from '../../../../ui/identicon'; - -// eslint-disable-next-line prefer-destructuring -const EIP_1559_V2 = process.env.EIP_1559_V2; +import { useGasFeeContext } from '../../../../../contexts/gasFee'; const ConfirmPageContainerSummary = (props) => { const { @@ -21,6 +19,8 @@ const ConfirmPageContainerSummary = (props) => { hideTitle, } = props; + const { supportsEIP1559V2 } = useGasFeeContext(); + return (
{origin === 'metamask' ? null : ( @@ -48,7 +48,7 @@ const ConfirmPageContainerSummary = (props) => {
) : null} - {!hideSubtitle && !EIP_1559_V2 && ( + {!hideSubtitle && !supportsEIP1559V2 && (
{subtitleComponent}
diff --git a/ui/components/app/confirm-page-container/confirm-page-container.component.js b/ui/components/app/confirm-page-container/confirm-page-container.component.js index 90e755b1d..996dd4019 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container.component.js @@ -1,24 +1,25 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import SenderToRecipient from '../../ui/sender-to-recipient'; -import { PageContainerFooter } from '../../ui/page-container'; -import EditGasPopover from '../edit-gas-popover'; + import { EDIT_GAS_MODES } from '../../../../shared/constants/gas'; import { GasFeeContextProvider } from '../../../contexts/gasFee'; -import ErrorMessage from '../../ui/error-message'; import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; + +import { PageContainerFooter } from '../../ui/page-container'; import Dialog from '../../ui/dialog'; +import ErrorMessage from '../../ui/error-message'; +import SenderToRecipient from '../../ui/sender-to-recipient'; + import AdvancedGasFeePopover from '../advanced-gas-fee-popover'; -import EditGasFeePopover from '../edit-gas-fee-popover'; +import EditGasFeePopover from '../edit-gas-fee-popover/edit-gas-fee-popover'; +import EditGasPopover from '../edit-gas-popover'; + import { ConfirmPageContainerHeader, ConfirmPageContainerContent, ConfirmPageContainerNavigation, } from '.'; -// eslint-disable-next-line prefer-destructuring -const EIP_1559_V2 = process.env.EIP_1559_V2; - export default class ConfirmPageContainer extends Component { static contextTypes = { t: PropTypes.func, @@ -77,6 +78,7 @@ export default class ConfirmPageContainer extends Component { showAddToAddressBookModal: PropTypes.func, contact: PropTypes.object, isOwnedAccount: PropTypes.bool, + supportsEIP1559V2: PropTypes.bool, }; render() { @@ -127,6 +129,7 @@ export default class ConfirmPageContainer extends Component { showAddToAddressBookModal, contact = {}, isOwnedAccount, + supportsEIP1559V2, } = this.props; const showAddToAddressDialog = @@ -208,6 +211,7 @@ export default class ConfirmPageContainer extends Component { origin={origin} ethGasPriceWarning={ethGasPriceWarning} hideTitle={hideTitle} + supportsEIP1559V2={supportsEIP1559V2} /> )} {shouldDisplayWarning && ( @@ -230,7 +234,7 @@ export default class ConfirmPageContainer extends Component { )}
)} - {editingGas && !EIP_1559_V2 && ( + {editingGas && !supportsEIP1559V2 && ( { @@ -50,7 +48,7 @@ export default function GasTiming({ const [customEstimatedTime, setCustomEstimatedTime] = useState(null); const t = useContext(I18nContext); - const { estimateUsed } = useGasFeeContext(); + const { estimateUsed, supportsEIP1559V2 } = useGasFeeContext(); // If the user has chosen a value lower than the low gas fee estimate, // We'll need to use the useEffect hook below to make a call to calculate @@ -97,7 +95,7 @@ export default function GasTiming({ ]); let unknownProcessingTimeText; - if (EIP_1559_V2) { + if (supportsEIP1559V2) { unknownProcessingTimeText = t('editGasTooLow'); } else { unknownProcessingTimeText = ( @@ -155,7 +153,7 @@ export default function GasTiming({ ]); } } else { - if (!EIP_1559_V2 || estimateUsed === 'low') { + if (!supportsEIP1559V2 || estimateUsed === 'low') { attitude = 'negative'; } // If the user has chosen a value less than our low estimate, @@ -176,7 +174,7 @@ export default function GasTiming({ } } // code below needs to cleaned-up once EIP_1559_V2 flag is removed - else if (EIP_1559_V2) { + else if (supportsEIP1559V2) { text = t('gasTimingNegative', [ toHumanReadableTime(low.maxWaitTimeEstimate, t), ]); @@ -199,8 +197,8 @@ export default function GasTiming({ {text} diff --git a/ui/components/app/transaction-detail/transaction-detail.component.js b/ui/components/app/transaction-detail/transaction-detail.component.js index e03d3f50f..919d76dac 100644 --- a/ui/components/app/transaction-detail/transaction-detail.component.js +++ b/ui/components/app/transaction-detail/transaction-detail.component.js @@ -16,9 +16,6 @@ export default function TransactionDetail({ onEdit, userAcknowledgedGasMissing, }) { - // eslint-disable-next-line prefer-destructuring - const EIP_1559_V2 = process.env.EIP_1559_V2; - const t = useI18nContext(); const { gasLimit, @@ -26,11 +23,12 @@ export default function TransactionDetail({ estimateUsed, maxFeePerGas, maxPriorityFeePerGas, + supportsEIP1559V2, transaction, } = useGasFeeContext(); const { openModal } = useTransactionModalContext(); - if (EIP_1559_V2 && estimateUsed) { + if (supportsEIP1559V2 && estimateUsed) { const editEnabled = !hasSimulationError || userAcknowledgedGasMissing; if (!editEnabled) return null; diff --git a/ui/components/app/transaction-detail/transaction-detail.component.test.js b/ui/components/app/transaction-detail/transaction-detail.component.test.js index 635ba7133..ee74034ec 100644 --- a/ui/components/app/transaction-detail/transaction-detail.component.test.js +++ b/ui/components/app/transaction-detail/transaction-detail.component.test.js @@ -1,9 +1,13 @@ import React from 'react'; import { screen } from '@testing-library/react'; -import { ETH } from '../../../helpers/constants/common'; +import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas'; +import { TRANSACTION_ENVELOPE_TYPES } from '../../../../shared/constants/transaction'; + import { GasFeeContextProvider } from '../../../contexts/gasFee'; import { renderWithProvider } from '../../../../test/jest'; +import mockEstimates from '../../../../test/data/mock-estimates.json'; +import mockState from '../../../../test/data/mock-state.json'; import configureStore from '../../../store/store'; import TransactionDetail from './transaction-detail.component'; @@ -19,20 +23,14 @@ jest.mock('../../../store/actions', () => ({ const render = ({ componentProps, contextProps } = {}) => { const store = configureStore({ metamask: { - nativeCurrency: ETH, - preferences: { - useNativeCurrencyAsPrimaryCurrency: true, - }, - provider: {}, - cachedBalances: {}, + ...mockState.metamask, accounts: { - '0xAddress': { - address: '0xAddress', - balance: '0x176e5b6f173ebe66', + [mockState.metamask.selectedAddress]: { + address: mockState.metamask.selectedAddress, + balance: '0x1F4', }, }, - selectedAddress: '0xAddress', - featureFlags: { advancedInlineGas: true }, + gasFeeEstimates: mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET], }, }); @@ -129,4 +127,17 @@ describe('TransactionDetail', () => { expect(screen.queryByRole('button')).toBeInTheDocument(); expect(screen.queryByText('Low')).toBeInTheDocument(); }); + + it('should render edit link with text edit for legacy transactions', () => { + render({ + contextProps: { + transaction: { + userFeeLevel: 'low', + txParams: { type: TRANSACTION_ENVELOPE_TYPES.LEGACY }, + }, + }, + }); + expect(screen.queryByText('🐢')).not.toBeInTheDocument(); + expect(screen.queryByText('Edit')).toBeInTheDocument(); + }); }); diff --git a/ui/hooks/gasFeeInput/useGasFeeInputs.js b/ui/hooks/gasFeeInput/useGasFeeInputs.js index 2d3a4747d..2c906f8e7 100644 --- a/ui/hooks/gasFeeInput/useGasFeeInputs.js +++ b/ui/hooks/gasFeeInput/useGasFeeInputs.js @@ -74,6 +74,10 @@ export function useGasFeeInputs( minimumGasLimit = '0x5208', editGasMode = EDIT_GAS_MODES.MODIFY_IN_PLACE, ) { + // eslint-disable-next-line prefer-destructuring + const EIP_1559_V2_ENABLED = + process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true'; + const supportsEIP1559 = useSelector(checkNetworkAndAccountSupports1559) && !isLegacyTransaction(transaction?.txParams); @@ -304,6 +308,7 @@ export function useGasFeeInputs( hasGasErrors, hasSimulationError, supportsEIP1559, + supportsEIP1559V2: supportsEIP1559 && EIP_1559_V2_ENABLED, updateTransactionUsingGasFeeEstimates, }; } diff --git a/ui/hooks/gasFeeInput/useGasFeeInputs.test.js b/ui/hooks/gasFeeInput/useGasFeeInputs.test.js index f32abbe32..f4bf4f908 100644 --- a/ui/hooks/gasFeeInput/useGasFeeInputs.test.js +++ b/ui/hooks/gasFeeInput/useGasFeeInputs.test.js @@ -316,4 +316,38 @@ describe('useGasFeeInputs', () => { expect(result.current.estimatedMinimumFiat).toBe(''); }); }); + + describe('supportsEIP1559V2', () => { + beforeEach(() => { + configureEIP1559(); + useSelector.mockImplementation( + generateUseSelectorRouter({ + checkNetworkAndAccountSupports1559Response: true, + }), + ); + process.env.EIP_1559_V2 = true; + }); + + afterEach(() => { + process.env.EIP_1559_V2 = false; + }); + + it('return true for fee_market transaction type', () => { + const { result } = renderHook(() => + useGasFeeInputs(null, { + txParams: { type: TRANSACTION_ENVELOPE_TYPES.FEE_MARKET }, + }), + ); + expect(result.current.supportsEIP1559V2).toBe(true); + }); + + it('return false for legacy transaction type', () => { + const { result } = renderHook(() => + useGasFeeInputs(null, { + txParams: { type: TRANSACTION_ENVELOPE_TYPES.LEGACY }, + }), + ); + expect(result.current.supportsEIP1559V2).toBe(false); + }); + }); }); diff --git a/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js index 8ac11d31f..6de9074c9 100644 --- a/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -26,7 +26,10 @@ import { TRANSACTION_STATUSES, } from '../../../shared/constants/transaction'; import { getMethodName } from '../../helpers/utils/metrics'; -import { getTransactionTypeTitle } from '../../helpers/utils/transactions.util'; +import { + getTransactionTypeTitle, + isLegacyTransaction, +} from '../../helpers/utils/transactions.util'; import { toBuffer } from '../../../shared/modules/buffer-utils'; import { TransactionModalContextProvider } from '../../contexts/transaction-modal'; @@ -57,7 +60,8 @@ import GasDetailsItem from './gas-details-item'; import TransactionAlerts from './transaction-alerts'; // eslint-disable-next-line prefer-destructuring -const EIP_1559_V2 = process.env.EIP_1559_V2; +const EIP_1559_V2_ENABLED = + process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true'; const renderHeartBeatIfNotInTest = () => process.env.IN_TEST === 'true' ? null : ; @@ -420,7 +424,9 @@ export default class ConfirmTransactionBase extends Component { ) : null; const renderGasDetailsItem = () => { - return EIP_1559_V2 ? ( + return EIP_1559_V2_ENABLED && + supportsEIP1559 && + !isLegacyTransaction(txData) ? ( - {EIP_1559_V2 && ( - - this.setUserAcknowledgedGasMissing() - } - userAcknowledgedGasMissing={userAcknowledgedGasMissing} - /> - )} + + this.setUserAcknowledgedGasMissing() + } + userAcknowledgedGasMissing={userAcknowledgedGasMissing} + /> this.handleCloseEditGas()} currentTransaction={txData} + supportsEIP1559V2={ + EIP_1559_V2_ENABLED && + supportsEIP1559 && + !isLegacyTransaction(txData) + } /> ); diff --git a/ui/pages/confirm-transaction-base/gas-details-item/gas-details-item.js b/ui/pages/confirm-transaction-base/gas-details-item/gas-details-item.js index d220cf683..91280266e 100644 --- a/ui/pages/confirm-transaction-base/gas-details-item/gas-details-item.js +++ b/ui/pages/confirm-transaction-base/gas-details-item/gas-details-item.js @@ -27,11 +27,10 @@ const GasDetailsItem = ({ maxFeePerGas, maxPriorityFeePerGas, userAcknowledgedGasMissing, - txData, useNativeCurrencyAsPrimaryCurrency, }) => { const t = useI18nContext(); - const { estimateUsed, hasSimulationError } = useGasFeeContext(); + const { estimateUsed, hasSimulationError, transaction } = useGasFeeContext(); if (hasSimulationError && !userAcknowledgedGasMissing) return null; @@ -124,10 +123,10 @@ const GasDetailsItem = ({ subTitle={ } @@ -142,7 +141,6 @@ GasDetailsItem.propTypes = { maxFeePerGas: PropTypes.string, maxPriorityFeePerGas: PropTypes.string, userAcknowledgedGasMissing: PropTypes.bool.isRequired, - txData: PropTypes.object, useNativeCurrencyAsPrimaryCurrency: PropTypes.bool, }; diff --git a/ui/pages/confirm-transaction-base/gas-details-item/gas-details-item.test.js b/ui/pages/confirm-transaction-base/gas-details-item/gas-details-item.test.js index 6e438b9e4..d149a6398 100644 --- a/ui/pages/confirm-transaction-base/gas-details-item/gas-details-item.test.js +++ b/ui/pages/confirm-transaction-base/gas-details-item/gas-details-item.test.js @@ -37,12 +37,8 @@ const render = ({ componentProps, contextProps } = {}) => { }); return renderWithProvider( - - + + , store, ); @@ -60,14 +56,18 @@ describe('GasDetailsItem', () => { }); it('should show warning icon if estimates are high', async () => { - render({ contextProps: { defaultEstimateToUse: 'high' } }); + render({ + contextProps: { transaction: { txParams: {}, userFeeLevel: 'high' } }, + }); await waitFor(() => { expect(screen.queryByText('⚠ Max fee:')).toBeInTheDocument(); }); }); it('should not show warning icon if estimates are not high', async () => { - render({ contextProps: { defaultEstimateToUse: 'low' } }); + render({ + contextProps: { transaction: { txParams: {}, userFeeLevel: 'low' } }, + }); await waitFor(() => { expect(screen.queryByText('Max fee:')).toBeInTheDocument(); }); @@ -76,8 +76,11 @@ describe('GasDetailsItem', () => { it('should return null if there is simulationError and user has not acknowledged gasMissing warning', () => { const { container } = render({ contextProps: { - defaultEstimateToUse: 'low', - transaction: { simulationFails: true }, + transaction: { + txParams: {}, + simulationFails: true, + userFeeLevel: 'low', + }, }, }); expect(container.innerHTML).toHaveLength(0); diff --git a/ui/pages/confirm-transaction-base/transaction-alerts/transaction-alerts.js b/ui/pages/confirm-transaction-base/transaction-alerts/transaction-alerts.js index 30061deaf..fe7d6a6ae 100644 --- a/ui/pages/confirm-transaction-base/transaction-alerts/transaction-alerts.js +++ b/ui/pages/confirm-transaction-base/transaction-alerts/transaction-alerts.js @@ -16,10 +16,17 @@ const TransactionAlerts = ({ userAcknowledgedGasMissing, setUserAcknowledgedGasMissing, }) => { - const { balanceError, estimateUsed, hasSimulationError } = useGasFeeContext(); + const { + balanceError, + estimateUsed, + hasSimulationError, + supportsEIP1559V2, + } = useGasFeeContext(); const pendingTransactions = useSelector(submittedPendingTransactionsSelector); const t = useI18nContext(); + if (!supportsEIP1559V2) return null; + return (
{hasSimulationError && ( diff --git a/ui/pages/confirm-transaction-base/transaction-alerts/transaction-alerts.test.js b/ui/pages/confirm-transaction-base/transaction-alerts/transaction-alerts.test.js index f9aa69d95..555a091a4 100644 --- a/ui/pages/confirm-transaction-base/transaction-alerts/transaction-alerts.test.js +++ b/ui/pages/confirm-transaction-base/transaction-alerts/transaction-alerts.test.js @@ -1,9 +1,14 @@ import React from 'react'; -import { screen } from '@testing-library/react'; +import { fireEvent, screen } from '@testing-library/react'; -import { ETH } from '../../../helpers/constants/common'; -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; +import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas'; +import { + TRANSACTION_ENVELOPE_TYPES, + TRANSACTION_STATUSES, +} from '../../../../shared/constants/transaction'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import mockEstimates from '../../../../test/data/mock-estimates.json'; +import mockState from '../../../../test/data/mock-state.json'; import { GasFeeContextProvider } from '../../../contexts/gasFee'; import configureStore from '../../../store/store'; @@ -17,44 +22,54 @@ jest.mock('../../../store/actions', () => ({ addPollingTokenToAppState: jest.fn(), })); -const render = ({ props, state } = {}) => { +const render = ({ componentProps, transactionProps, state }) => { const store = configureStore({ metamask: { - nativeCurrency: ETH, - preferences: { - useNativeCurrencyAsPrimaryCurrency: true, - }, - provider: {}, - cachedBalances: {}, + ...mockState.metamask, accounts: { - '0xAddress': { - address: '0xAddress', + [mockState.metamask.selectedAddress]: { + address: mockState.metamask.selectedAddress, balance: '0x1F4', }, }, - selectedAddress: '0xAddress', + gasFeeEstimates: mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET], ...state, }, }); return renderWithProvider( - - + + , store, ); }; describe('TransactionAlerts', () => { + beforeEach(() => { + process.env.EIP_1559_V2 = true; + }); + + afterEach(() => { + process.env.EIP_1559_V2 = false; + }); + it('should returning warning message for low gas estimate', () => { - render({ props: { transaction: { userFeeLevel: 'low' } } }); + render({ transactionProps: { userFeeLevel: 'low' } }); expect( document.getElementsByClassName('actionable-message--warning'), ).toHaveLength(1); }); it('should return null for gas estimate other than low', () => { - render({ props: { transaction: { userFeeLevel: 'high' } } }); + render({ transactionProps: { userFeeLevel: 'high' } }); expect( document.getElementsByClassName('actionable-message--warning'), ).toHaveLength(0); @@ -62,8 +77,9 @@ describe('TransactionAlerts', () => { it('should not show insufficient balance message if transaction value is less than balance', () => { render({ - props: { - transaction: { userFeeLevel: 'high', txParams: { value: '0x64' } }, + transactionProps: { + userFeeLevel: 'high', + txParams: { value: '0x64' }, }, }); expect(screen.queryByText('Insufficient funds.')).not.toBeInTheDocument(); @@ -71,8 +87,9 @@ describe('TransactionAlerts', () => { it('should show insufficient balance message if transaction value is more than balance', () => { render({ - props: { - transaction: { userFeeLevel: 'high', txParams: { value: '0x5208' } }, + transactionProps: { + userFeeLevel: 'high', + txParams: { value: '0x5208' }, }, }); expect(screen.queryByText('Insufficient funds.')).toBeInTheDocument(); @@ -86,7 +103,7 @@ describe('TransactionAlerts', () => { id: 0, time: 0, txParams: { - from: '0xAddress', + from: mockState.metamask.selectedAddress, to: '0xRecipient', }, status: TRANSACTION_STATUSES.SUBMITTED, @@ -98,4 +115,58 @@ describe('TransactionAlerts', () => { screen.queryByText('You have (1) pending transaction.'), ).toBeInTheDocument(); }); + + describe('SimulationError Message', () => { + it('should show simulation error message along with option to proceed anyway if transaction.simulationFails is true', () => { + render({ transactionProps: { simulationFails: true } }); + expect( + screen.queryByText( + 'We were not able to estimate gas. There might be an error in the contract and this transaction may fail.', + ), + ).toBeInTheDocument(); + expect( + screen.queryByText('I want to proceed anyway'), + ).toBeInTheDocument(); + }); + + it('should not show options to acknowledge gas-missing warning if component prop userAcknowledgedGasMissing is already true', () => { + render({ + componentProps: { + userAcknowledgedGasMissing: true, + }, + transactionProps: { simulationFails: true }, + }); + expect( + screen.queryByText( + 'We were not able to estimate gas. There might be an error in the contract and this transaction may fail.', + ), + ).toBeInTheDocument(); + expect( + screen.queryByText('I want to proceed anyway'), + ).not.toBeInTheDocument(); + }); + + it('should call prop setUserAcknowledgedGasMissing if option to acknowledge gas-missing warning is clicked', () => { + const setUserAcknowledgedGasMissing = jest.fn(); + render({ + componentProps: { + setUserAcknowledgedGasMissing, + }, + transactionProps: { simulationFails: true }, + }); + fireEvent.click(screen.queryByText('I want to proceed anyway')); + expect(setUserAcknowledgedGasMissing).toHaveBeenCalledTimes(1); + }); + + it('should return null for legacy transactions', () => { + const { container } = render({ + transactionProps: { + txParams: { + type: TRANSACTION_ENVELOPE_TYPES.LEGACY, + }, + }, + }); + expect(container.firstChild).toBeNull(); + }); + }); });