aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/pages/send/send-content/send-gas-row
diff options
context:
space:
mode:
authorDan Finlay <542863+danfinlay@users.noreply.github.com>2019-04-25 03:25:39 +0800
committerGitHub <noreply@github.com>2019-04-25 03:25:39 +0800
commit87d5be9081fd3ab3bfb4ae67d5cab4b8a8304a8a (patch)
tree2230335f440e36c23f47e0794e94cf6b0b312024 /ui/app/pages/send/send-content/send-gas-row
parent8c98e89e617b594d4f0ee54a8437e30201688090 (diff)
parent6a60562d6649d88f24bd849b325871bb256a0001 (diff)
downloadtangerine-wallet-browser-87d5be9081fd3ab3bfb4ae67d5cab4b8a8304a8a.tar.gz
tangerine-wallet-browser-87d5be9081fd3ab3bfb4ae67d5cab4b8a8304a8a.tar.zst
tangerine-wallet-browser-87d5be9081fd3ab3bfb4ae67d5cab4b8a8304a8a.zip
Merge pull request #6484 from MetaMask/develop
Update master branch with develop (v6.4.0)
Diffstat (limited to 'ui/app/pages/send/send-content/send-gas-row')
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/README.md0
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js57
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js1
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js61
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/index.js1
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js131
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js118
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss0
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/send-gas-row.selectors.js19
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js104
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js200
-rw-r--r--ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-selectors.test.js62
12 files changed, 754 insertions, 0 deletions
diff --git a/ui/app/pages/send/send-content/send-gas-row/README.md b/ui/app/pages/send/send-content/send-gas-row/README.md
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/README.md
diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js
new file mode 100644
index 000000000..3f5587318
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js
@@ -0,0 +1,57 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import UserPreferencedCurrencyDisplay from '../../../../../components/app/user-preferenced-currency-display'
+import { PRIMARY, SECONDARY } from '../../../../../helpers/constants/common'
+
+export default class GasFeeDisplay extends Component {
+
+ static propTypes = {
+ conversionRate: PropTypes.number,
+ primaryCurrency: PropTypes.string,
+ convertedCurrency: PropTypes.string,
+ gasLoadingError: PropTypes.bool,
+ gasTotal: PropTypes.string,
+ onReset: PropTypes.func,
+ };
+
+ static contextTypes = {
+ t: PropTypes.func,
+ };
+
+ render () {
+ const { gasTotal, gasLoadingError, onReset } = this.props
+
+ return (
+ <div className="send-v2__gas-fee-display">
+ {gasTotal
+ ? (
+ <div className="currency-display">
+ <UserPreferencedCurrencyDisplay
+ value={gasTotal}
+ type={PRIMARY}
+ />
+ <UserPreferencedCurrencyDisplay
+ className="currency-display__converted-value"
+ value={gasTotal}
+ type={SECONDARY}
+ />
+ </div>
+ )
+ : gasLoadingError
+ ? <div className="currency-display.currency-display--message">
+ {this.context.t('setGasPrice')}
+ </div>
+ : <div className="currency-display">
+ {this.context.t('loading')}
+ </div>
+ }
+ <button
+ className="gas-fee-reset"
+ onClick={onReset}
+ >
+ { this.context.t('reset') }
+ </button>
+ </div>
+ )
+ }
+}
diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js
new file mode 100644
index 000000000..dba0edb7b
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js
@@ -0,0 +1 @@
+export { default } from './gas-fee-display.component'
diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js
new file mode 100644
index 000000000..eedd43221
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/test/gas-fee-display.component.test.js
@@ -0,0 +1,61 @@
+import React from 'react'
+import assert from 'assert'
+import {shallow} from 'enzyme'
+import GasFeeDisplay from '../gas-fee-display.component'
+import UserPreferencedCurrencyDisplay from '../../../../../../components/app/user-preferenced-currency-display'
+import sinon from 'sinon'
+
+
+const propsMethodSpies = {
+ showCustomizeGasModal: sinon.spy(),
+ onReset: sinon.spy(),
+}
+
+describe('GasFeeDisplay Component', function () {
+ let wrapper
+
+ beforeEach(() => {
+ wrapper = shallow(<GasFeeDisplay
+ conversionRate={20}
+ gasTotal={'mockGasTotal'}
+ primaryCurrency={'mockPrimaryCurrency'}
+ convertedCurrency={'mockConvertedCurrency'}
+ showGasButtonGroup={propsMethodSpies.showCustomizeGasModal}
+ onReset={propsMethodSpies.onReset}
+ />, {context: {t: str => str + '_t'}})
+ })
+
+ afterEach(() => {
+ propsMethodSpies.showCustomizeGasModal.resetHistory()
+ })
+
+ describe('render', () => {
+ it('should render a CurrencyDisplay component', () => {
+ assert.equal(wrapper.find(UserPreferencedCurrencyDisplay).length, 2)
+ })
+
+ it('should render the CurrencyDisplay with the correct props', () => {
+ const {
+ type,
+ value,
+ } = wrapper.find(UserPreferencedCurrencyDisplay).at(0).props()
+ assert.equal(type, 'PRIMARY')
+ assert.equal(value, 'mockGasTotal')
+ })
+
+ it('should render the reset button with the correct props', () => {
+ const {
+ onClick,
+ className,
+ } = wrapper.find('button').props()
+ assert.equal(className, 'gas-fee-reset')
+ assert.equal(propsMethodSpies.onReset.callCount, 0)
+ onClick()
+ assert.equal(propsMethodSpies.onReset.callCount, 1)
+ })
+
+ it('should render the reset button with the correct text', () => {
+ assert.equal(wrapper.find('button').text(), 'reset_t')
+ })
+ })
+})
diff --git a/ui/app/pages/send/send-content/send-gas-row/index.js b/ui/app/pages/send/send-content/send-gas-row/index.js
new file mode 100644
index 000000000..3c7ff1d5f
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/index.js
@@ -0,0 +1 @@
+export { default } from './send-gas-row.container'
diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js
new file mode 100644
index 000000000..1b850ac57
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js
@@ -0,0 +1,131 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import SendRowWrapper from '../send-row-wrapper'
+import GasFeeDisplay from './gas-fee-display/gas-fee-display.component'
+import GasPriceButtonGroup from '../../../../components/app/gas-customization/gas-price-button-group'
+import AdvancedGasInputs from '../../../../components/app/gas-customization/advanced-gas-inputs'
+
+export default class SendGasRow extends Component {
+
+ static propTypes = {
+ conversionRate: PropTypes.number,
+ convertedCurrency: PropTypes.string,
+ gasFeeError: PropTypes.bool,
+ gasLoadingError: PropTypes.bool,
+ gasTotal: PropTypes.string,
+ showCustomizeGasModal: PropTypes.func,
+ setGasPrice: PropTypes.func,
+ setGasLimit: PropTypes.func,
+ gasPriceButtonGroupProps: PropTypes.object,
+ gasButtonGroupShown: PropTypes.bool,
+ advancedInlineGasShown: PropTypes.bool,
+ resetGasButtons: PropTypes.func,
+ gasPrice: PropTypes.string,
+ gasLimit: PropTypes.string,
+ insufficientBalance: PropTypes.bool,
+ }
+
+ static contextTypes = {
+ t: PropTypes.func,
+ metricsEvent: PropTypes.func,
+ };
+
+ renderAdvancedOptionsButton () {
+ const { metricsEvent } = this.context
+ const { showCustomizeGasModal } = this.props
+ return <div className="advanced-gas-options-btn" onClick={() => {
+ metricsEvent({
+ eventOpts: {
+ category: 'Transactions',
+ action: 'Edit Screen',
+ name: 'Clicked "Advanced Options"',
+ },
+ })
+ showCustomizeGasModal()
+ }}>
+ { this.context.t('advancedOptions') }
+ </div>
+ }
+
+ renderContent () {
+ const {
+ conversionRate,
+ convertedCurrency,
+ gasLoadingError,
+ gasTotal,
+ showCustomizeGasModal,
+ gasPriceButtonGroupProps,
+ gasButtonGroupShown,
+ advancedInlineGasShown,
+ resetGasButtons,
+ setGasPrice,
+ setGasLimit,
+ gasPrice,
+ gasLimit,
+ insufficientBalance,
+ } = this.props
+ const { metricsEvent } = this.context
+
+ const gasPriceButtonGroup = <div>
+ <GasPriceButtonGroup
+ className="gas-price-button-group--small"
+ showCheck={false}
+ {...gasPriceButtonGroupProps}
+ handleGasPriceSelection={(...args) => {
+ metricsEvent({
+ eventOpts: {
+ category: 'Transactions',
+ action: 'Edit Screen',
+ name: 'Changed Gas Button',
+ },
+ })
+ gasPriceButtonGroupProps.handleGasPriceSelection(...args)
+ }}
+ />
+ { this.renderAdvancedOptionsButton() }
+ </div>
+ const gasFeeDisplay = <GasFeeDisplay
+ conversionRate={conversionRate}
+ convertedCurrency={convertedCurrency}
+ gasLoadingError={gasLoadingError}
+ gasTotal={gasTotal}
+ onReset={resetGasButtons}
+ onClick={() => showCustomizeGasModal()}
+ />
+ const advancedGasInputs = <div>
+ <AdvancedGasInputs
+ updateCustomGasPrice={newGasPrice => setGasPrice(newGasPrice, gasLimit)}
+ updateCustomGasLimit={newGasLimit => setGasLimit(newGasLimit, gasPrice)}
+ customGasPrice={gasPrice}
+ customGasLimit={gasLimit}
+ insufficientBalance={insufficientBalance}
+ customPriceIsSafe={true}
+ isSpeedUp={false}
+ />
+ { this.renderAdvancedOptionsButton() }
+ </div>
+
+ if (advancedInlineGasShown) {
+ return advancedGasInputs
+ } else if (gasButtonGroupShown) {
+ return gasPriceButtonGroup
+ } else {
+ return gasFeeDisplay
+ }
+ }
+
+ render () {
+ const { gasFeeError } = this.props
+
+ return (
+ <SendRowWrapper
+ label={`${this.context.t('transactionFee')}:`}
+ showError={gasFeeError}
+ errorType={'gasFee'}
+ >
+ { this.renderContent() }
+ </SendRowWrapper>
+ )
+ }
+
+}
diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js
new file mode 100644
index 000000000..c4daa98af
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js
@@ -0,0 +1,118 @@
+import { connect } from 'react-redux'
+import {
+ getConversionRate,
+ getCurrentCurrency,
+ getGasTotal,
+ getGasPrice,
+ getGasLimit,
+ getSendAmount,
+} from '../../send.selectors.js'
+import {
+ isBalanceSufficient,
+ calcGasTotal,
+} from '../../send.utils.js'
+import {
+ getBasicGasEstimateLoadingStatus,
+ getRenderableEstimateDataForSmallButtonsFromGWEI,
+ getDefaultActiveButtonIndex,
+} from '../../../../selectors/custom-gas'
+import {
+ showGasButtonGroup,
+} from '../../../../ducks/send/send.duck'
+import {
+ resetCustomData,
+ setCustomGasPrice,
+ setCustomGasLimit,
+} from '../../../../ducks/gas/gas.duck'
+import { getGasLoadingError, gasFeeIsInError, getGasButtonGroupShown } from './send-gas-row.selectors.js'
+import { showModal, setGasPrice, setGasLimit, setGasTotal } from '../../../../store/actions'
+import { getAdvancedInlineGasShown, getCurrentEthBalance, getSelectedToken } from '../../../../selectors/selectors'
+import SendGasRow from './send-gas-row.component'
+
+export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(SendGasRow)
+
+function mapStateToProps (state) {
+ const gasButtonInfo = getRenderableEstimateDataForSmallButtonsFromGWEI(state)
+ const gasPrice = getGasPrice(state)
+ const gasLimit = getGasLimit(state)
+ const activeButtonIndex = getDefaultActiveButtonIndex(gasButtonInfo, gasPrice)
+
+ const gasTotal = getGasTotal(state)
+ const conversionRate = getConversionRate(state)
+ const balance = getCurrentEthBalance(state)
+
+ const insufficientBalance = !isBalanceSufficient({
+ amount: getSelectedToken(state) ? '0x0' : getSendAmount(state),
+ gasTotal,
+ balance,
+ conversionRate,
+ })
+
+ return {
+ conversionRate,
+ convertedCurrency: getCurrentCurrency(state),
+ gasTotal,
+ gasFeeError: gasFeeIsInError(state),
+ gasLoadingError: getGasLoadingError(state),
+ gasPriceButtonGroupProps: {
+ buttonDataLoading: getBasicGasEstimateLoadingStatus(state),
+ defaultActiveButtonIndex: 1,
+ newActiveButtonIndex: activeButtonIndex > -1 ? activeButtonIndex : null,
+ gasButtonInfo,
+ },
+ gasButtonGroupShown: getGasButtonGroupShown(state),
+ advancedInlineGasShown: getAdvancedInlineGasShown(state),
+ gasPrice,
+ gasLimit,
+ insufficientBalance,
+ }
+}
+
+function mapDispatchToProps (dispatch) {
+ return {
+ showCustomizeGasModal: () => dispatch(showModal({ name: 'CUSTOMIZE_GAS', hideBasic: true })),
+ setGasPrice: (newPrice, gasLimit) => {
+ dispatch(setGasPrice(newPrice))
+ dispatch(setCustomGasPrice(newPrice))
+ if (gasLimit) {
+ dispatch(setGasTotal(calcGasTotal(gasLimit, newPrice)))
+ }
+ },
+ setGasLimit: (newLimit, gasPrice) => {
+ dispatch(setGasLimit(newLimit))
+ dispatch(setCustomGasLimit(newLimit))
+ if (gasPrice) {
+ dispatch(setGasTotal(calcGasTotal(newLimit, gasPrice)))
+ }
+ },
+ showGasButtonGroup: () => dispatch(showGasButtonGroup()),
+ resetCustomData: () => dispatch(resetCustomData()),
+ }
+}
+
+function mergeProps (stateProps, dispatchProps, ownProps) {
+ const { gasPriceButtonGroupProps } = stateProps
+ const { gasButtonInfo } = gasPriceButtonGroupProps
+ const {
+ setGasPrice: dispatchSetGasPrice,
+ showGasButtonGroup: dispatchShowGasButtonGroup,
+ resetCustomData: dispatchResetCustomData,
+ ...otherDispatchProps
+ } = dispatchProps
+
+ return {
+ ...stateProps,
+ ...otherDispatchProps,
+ ...ownProps,
+ gasPriceButtonGroupProps: {
+ ...gasPriceButtonGroupProps,
+ handleGasPriceSelection: dispatchSetGasPrice,
+ },
+ resetGasButtons: () => {
+ dispatchResetCustomData()
+ dispatchSetGasPrice(gasButtonInfo[1].priceInHexWei)
+ dispatchShowGasButtonGroup()
+ },
+ setGasPrice: dispatchSetGasPrice,
+ }
+}
diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss
diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.selectors.js b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.selectors.js
new file mode 100644
index 000000000..79c838543
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.selectors.js
@@ -0,0 +1,19 @@
+const selectors = {
+ gasFeeIsInError,
+ getGasLoadingError,
+ getGasButtonGroupShown,
+}
+
+module.exports = selectors
+
+function getGasLoadingError (state) {
+ return state.send.errors.gasLoading
+}
+
+function gasFeeIsInError (state) {
+ return Boolean(state.send.errors.gasFee)
+}
+
+function getGasButtonGroupShown (state) {
+ return state.send.gasButtonGroupShown
+}
diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js
new file mode 100644
index 000000000..0cbc92621
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-component.test.js
@@ -0,0 +1,104 @@
+import React from 'react'
+import assert from 'assert'
+import { shallow } from 'enzyme'
+import sinon from 'sinon'
+import SendGasRow from '../send-gas-row.component.js'
+
+import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component'
+import GasFeeDisplay from '../gas-fee-display/gas-fee-display.component'
+import GasPriceButtonGroup from '../../../../../components/app/gas-customization/gas-price-button-group'
+
+const propsMethodSpies = {
+ showCustomizeGasModal: sinon.spy(),
+ resetGasButtons: sinon.spy(),
+}
+
+describe('SendGasRow Component', function () {
+ let wrapper
+
+ beforeEach(() => {
+ wrapper = shallow(<SendGasRow
+ conversionRate={20}
+ convertedCurrency={'mockConvertedCurrency'}
+ gasFeeError={'mockGasFeeError'}
+ gasLoadingError={false}
+ gasTotal={'mockGasTotal'}
+ gasButtonGroupShown={false}
+ showCustomizeGasModal={propsMethodSpies.showCustomizeGasModal}
+ resetGasButtons={propsMethodSpies.resetGasButtons}
+ gasPriceButtonGroupProps={{
+ someGasPriceButtonGroupProp: 'foo',
+ anotherGasPriceButtonGroupProp: 'bar',
+ }}
+ />, { context: { t: str => str + '_t', metricsEvent: () => ({}) } })
+ })
+
+ afterEach(() => {
+ propsMethodSpies.resetGasButtons.resetHistory()
+ })
+
+ describe('render', () => {
+ it('should render a SendRowWrapper component', () => {
+ assert.equal(wrapper.find(SendRowWrapper).length, 1)
+ })
+
+ it('should pass the correct props to SendRowWrapper', () => {
+ const {
+ label,
+ showError,
+ errorType,
+ } = wrapper.find(SendRowWrapper).props()
+
+ assert.equal(label, 'transactionFee_t:')
+ assert.equal(showError, 'mockGasFeeError')
+ assert.equal(errorType, 'gasFee')
+ })
+
+ it('should render a GasFeeDisplay as a child of the SendRowWrapper', () => {
+ assert(wrapper.find(SendRowWrapper).childAt(0).is(GasFeeDisplay))
+ })
+
+ it('should render the GasFeeDisplay with the correct props', () => {
+ const {
+ conversionRate,
+ convertedCurrency,
+ gasLoadingError,
+ gasTotal,
+ onReset,
+ } = wrapper.find(SendRowWrapper).childAt(0).props()
+ assert.equal(conversionRate, 20)
+ assert.equal(convertedCurrency, 'mockConvertedCurrency')
+ assert.equal(gasLoadingError, false)
+ assert.equal(gasTotal, 'mockGasTotal')
+ assert.equal(propsMethodSpies.resetGasButtons.callCount, 0)
+ onReset()
+ assert.equal(propsMethodSpies.resetGasButtons.callCount, 1)
+ })
+
+ it('should render the GasPriceButtonGroup if gasButtonGroupShown is true', () => {
+ wrapper.setProps({ gasButtonGroupShown: true })
+ const rendered = wrapper.find(SendRowWrapper).childAt(0)
+ assert.equal(rendered.children().length, 2)
+
+ const gasPriceButtonGroup = rendered.childAt(0)
+ assert(gasPriceButtonGroup.is(GasPriceButtonGroup))
+ assert(gasPriceButtonGroup.hasClass('gas-price-button-group--small'))
+ assert.equal(gasPriceButtonGroup.props().showCheck, false)
+ assert.equal(gasPriceButtonGroup.props().someGasPriceButtonGroupProp, 'foo')
+ assert.equal(gasPriceButtonGroup.props().anotherGasPriceButtonGroupProp, 'bar')
+ })
+
+ it('should render an advanced options button if gasButtonGroupShown is true', () => {
+ wrapper.setProps({ gasButtonGroupShown: true })
+ const rendered = wrapper.find(SendRowWrapper).childAt(0)
+ assert.equal(rendered.children().length, 2)
+
+ const advancedOptionsButton = rendered.childAt(1)
+ assert.equal(advancedOptionsButton.text(), 'advancedOptions_t')
+
+ assert.equal(propsMethodSpies.showCustomizeGasModal.callCount, 0)
+ advancedOptionsButton.props().onClick()
+ assert.equal(propsMethodSpies.showCustomizeGasModal.callCount, 1)
+ })
+ })
+})
diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js
new file mode 100644
index 000000000..ddc6ea985
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js
@@ -0,0 +1,200 @@
+import assert from 'assert'
+import proxyquire from 'proxyquire'
+import sinon from 'sinon'
+
+let mapStateToProps
+let mapDispatchToProps
+let mergeProps
+
+const actionSpies = {
+ showModal: sinon.spy(),
+ setGasPrice: sinon.spy(),
+ setGasTotal: sinon.spy(),
+ setGasLimit: sinon.spy(),
+}
+
+const sendDuckSpies = {
+ showGasButtonGroup: sinon.spy(),
+}
+
+const gasDuckSpies = {
+ resetCustomData: sinon.spy(),
+ setCustomGasPrice: sinon.spy(),
+ setCustomGasLimit: sinon.spy(),
+}
+
+proxyquire('../send-gas-row.container.js', {
+ 'react-redux': {
+ connect: (ms, md, mp) => {
+ mapStateToProps = ms
+ mapDispatchToProps = md
+ mergeProps = mp
+ return () => ({})
+ },
+ },
+ '../../../../selectors/selectors': {
+ getCurrentEthBalance: (s) => `mockCurrentEthBalance:${s}`,
+ getAdvancedInlineGasShown: (s) => `mockAdvancedInlineGasShown:${s}`,
+ getSelectedToken: () => false,
+ },
+ '../../send.selectors.js': {
+ getConversionRate: (s) => `mockConversionRate:${s}`,
+ getCurrentCurrency: (s) => `mockConvertedCurrency:${s}`,
+ getGasTotal: (s) => `mockGasTotal:${s}`,
+ getGasPrice: (s) => `mockGasPrice:${s}`,
+ getGasLimit: (s) => `mockGasLimit:${s}`,
+ getSendAmount: (s) => `mockSendAmount:${s}`,
+ },
+ '../../send.utils.js': {
+ isBalanceSufficient: ({
+ amount,
+ gasTotal,
+ balance,
+ conversionRate,
+ }) => `${amount}:${gasTotal}:${balance}:${conversionRate}`,
+ calcGasTotal: (gasLimit, gasPrice) => gasLimit + gasPrice,
+ },
+ './send-gas-row.selectors.js': {
+ getGasLoadingError: (s) => `mockGasLoadingError:${s}`,
+ gasFeeIsInError: (s) => `mockGasFeeError:${s}`,
+ getGasButtonGroupShown: (s) => `mockGetGasButtonGroupShown:${s}`,
+ },
+ '../../../../store/actions': actionSpies,
+ '../../../../selectors/custom-gas': {
+ getBasicGasEstimateLoadingStatus: (s) => `mockBasicGasEstimateLoadingStatus:${s}`,
+ getRenderableEstimateDataForSmallButtonsFromGWEI: (s) => `mockGasButtonInfo:${s}`,
+ getDefaultActiveButtonIndex: (gasButtonInfo, gasPrice) => gasButtonInfo.length + gasPrice.length,
+ },
+ '../../../../ducks/send/send.duck': sendDuckSpies,
+ '../../../../ducks/gas/gas.duck': gasDuckSpies,
+})
+
+describe('send-gas-row container', () => {
+
+ describe('mapStateToProps()', () => {
+
+ it('should map the correct properties to props', () => {
+ assert.deepEqual(mapStateToProps('mockState'), {
+ conversionRate: 'mockConversionRate:mockState',
+ convertedCurrency: 'mockConvertedCurrency:mockState',
+ gasTotal: 'mockGasTotal:mockState',
+ gasFeeError: 'mockGasFeeError:mockState',
+ gasLoadingError: 'mockGasLoadingError:mockState',
+ gasPriceButtonGroupProps: {
+ buttonDataLoading: `mockBasicGasEstimateLoadingStatus:mockState`,
+ defaultActiveButtonIndex: 1,
+ newActiveButtonIndex: 49,
+ gasButtonInfo: `mockGasButtonInfo:mockState`,
+ },
+ gasButtonGroupShown: `mockGetGasButtonGroupShown:mockState`,
+ advancedInlineGasShown: 'mockAdvancedInlineGasShown:mockState',
+ gasLimit: 'mockGasLimit:mockState',
+ gasPrice: 'mockGasPrice:mockState',
+ insufficientBalance: false,
+ })
+ })
+
+ })
+
+ describe('mapDispatchToProps()', () => {
+ let dispatchSpy
+ let mapDispatchToPropsObject
+
+ beforeEach(() => {
+ dispatchSpy = sinon.spy()
+ mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy)
+ actionSpies.setGasTotal.resetHistory()
+ })
+
+ describe('showCustomizeGasModal()', () => {
+ it('should dispatch an action', () => {
+ mapDispatchToPropsObject.showCustomizeGasModal()
+ assert(dispatchSpy.calledOnce)
+ assert.deepEqual(
+ actionSpies.showModal.getCall(0).args[0],
+ { name: 'CUSTOMIZE_GAS', hideBasic: true }
+ )
+ })
+ })
+
+ describe('setGasPrice()', () => {
+ it('should dispatch an action', () => {
+ mapDispatchToPropsObject.setGasPrice('mockNewPrice', 'mockLimit')
+ assert(dispatchSpy.calledThrice)
+ assert(actionSpies.setGasPrice.calledOnce)
+ assert.equal(actionSpies.setGasPrice.getCall(0).args[0], 'mockNewPrice')
+ assert.equal(gasDuckSpies.setCustomGasPrice.getCall(0).args[0], 'mockNewPrice')
+ assert(actionSpies.setGasTotal.calledOnce)
+ assert.equal(actionSpies.setGasTotal.getCall(0).args[0], 'mockLimitmockNewPrice')
+ })
+ })
+
+ describe('setGasLimit()', () => {
+ it('should dispatch an action', () => {
+ mapDispatchToPropsObject.setGasLimit('mockNewLimit', 'mockPrice')
+ assert(dispatchSpy.calledThrice)
+ assert(actionSpies.setGasLimit.calledOnce)
+ assert.equal(actionSpies.setGasLimit.getCall(0).args[0], 'mockNewLimit')
+ assert.equal(gasDuckSpies.setCustomGasLimit.getCall(0).args[0], 'mockNewLimit')
+ assert(actionSpies.setGasTotal.calledOnce)
+ assert.equal(actionSpies.setGasTotal.getCall(0).args[0], 'mockNewLimitmockPrice')
+ })
+ })
+
+ describe('showGasButtonGroup()', () => {
+ it('should dispatch an action', () => {
+ mapDispatchToPropsObject.showGasButtonGroup()
+ assert(dispatchSpy.calledOnce)
+ assert(sendDuckSpies.showGasButtonGroup.calledOnce)
+ })
+ })
+
+ describe('resetCustomData()', () => {
+ it('should dispatch an action', () => {
+ mapDispatchToPropsObject.resetCustomData()
+ assert(dispatchSpy.calledOnce)
+ assert(gasDuckSpies.resetCustomData.calledOnce)
+ })
+ })
+
+ })
+
+ describe('mergeProps', () => {
+ let stateProps
+ let dispatchProps
+ let ownProps
+
+ beforeEach(() => {
+ stateProps = {
+ gasPriceButtonGroupProps: {
+ someGasPriceButtonGroupProp: 'foo',
+ anotherGasPriceButtonGroupProp: 'bar',
+ },
+ someOtherStateProp: 'baz',
+ }
+ dispatchProps = {
+ setGasPrice: sinon.spy(),
+ someOtherDispatchProp: sinon.spy(),
+ }
+ ownProps = { someOwnProp: 123 }
+ })
+
+ it('should return the expected props when isConfirm is true', () => {
+ const result = mergeProps(stateProps, dispatchProps, ownProps)
+
+ assert.equal(result.someOtherStateProp, 'baz')
+ assert.equal(result.gasPriceButtonGroupProps.someGasPriceButtonGroupProp, 'foo')
+ assert.equal(result.gasPriceButtonGroupProps.anotherGasPriceButtonGroupProp, 'bar')
+ assert.equal(result.someOwnProp, 123)
+
+ assert.equal(dispatchProps.setGasPrice.callCount, 0)
+ result.gasPriceButtonGroupProps.handleGasPriceSelection()
+ assert.equal(dispatchProps.setGasPrice.callCount, 1)
+
+ assert.equal(dispatchProps.someOtherDispatchProp.callCount, 0)
+ result.someOtherDispatchProp()
+ assert.equal(dispatchProps.someOtherDispatchProp.callCount, 1)
+ })
+ })
+
+})
diff --git a/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-selectors.test.js b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-selectors.test.js
new file mode 100644
index 000000000..bd3c9a257
--- /dev/null
+++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-selectors.test.js
@@ -0,0 +1,62 @@
+import assert from 'assert'
+import {
+ gasFeeIsInError,
+ getGasLoadingError,
+ getGasButtonGroupShown,
+} from '../send-gas-row.selectors.js'
+
+describe('send-gas-row selectors', () => {
+
+ describe('getGasLoadingError()', () => {
+ it('should return send.errors.gasLoading', () => {
+ const state = {
+ send: {
+ errors: {
+ gasLoading: 'abc',
+ },
+ },
+ }
+
+ assert.equal(getGasLoadingError(state), 'abc')
+ })
+ })
+
+ describe('gasFeeIsInError()', () => {
+ it('should return true if send.errors.gasFee is truthy', () => {
+ const state = {
+ send: {
+ errors: {
+ gasFee: 'def',
+ },
+ },
+ }
+
+ assert.equal(gasFeeIsInError(state), true)
+ })
+
+ it('should return false send.errors.gasFee is falsely', () => {
+ const state = {
+ send: {
+ errors: {
+ gasFee: null,
+ },
+ },
+ }
+
+ assert.equal(gasFeeIsInError(state), false)
+ })
+ })
+
+ describe('getGasButtonGroupShown()', () => {
+ it('should return send.gasButtonGroupShown', () => {
+ const state = {
+ send: {
+ gasButtonGroupShown: 'foobar',
+ },
+ }
+
+ assert.equal(getGasButtonGroupShown(state), 'foobar')
+ })
+ })
+
+})