diff options
author | pldespaigne <pl.despaigne@gmail.com> | 2019-05-31 00:22:55 +0800 |
---|---|---|
committer | pldespaigne <pl.despaigne@gmail.com> | 2019-05-31 00:22:55 +0800 |
commit | 9a658ee53d1f75ce07c33581ac1189fa8c4fd173 (patch) | |
tree | ea92ef1971ffaa72c29bf16904906bc1841654c7 /ui/app/pages/send/send-content/send-gas-row | |
parent | 9b87aaae1907eb04ca0a4055b5bb2c863e56aa39 (diff) | |
parent | 681f3f67b89b64fc837df1103198b641c7e7b2d6 (diff) | |
download | tangerine-wallet-browser-9a658ee53d1f75ce07c33581ac1189fa8c4fd173.tar tangerine-wallet-browser-9a658ee53d1f75ce07c33581ac1189fa8c4fd173.tar.gz tangerine-wallet-browser-9a658ee53d1f75ce07c33581ac1189fa8c4fd173.tar.bz2 tangerine-wallet-browser-9a658ee53d1f75ce07c33581ac1189fa8c4fd173.tar.lz tangerine-wallet-browser-9a658ee53d1f75ce07c33581ac1189fa8c4fd173.tar.xz tangerine-wallet-browser-9a658ee53d1f75ce07c33581ac1189fa8c4fd173.tar.zst tangerine-wallet-browser-9a658ee53d1f75ce07c33581ac1189fa8c4fd173.zip |
merge
Diffstat (limited to 'ui/app/pages/send/send-content/send-gas-row')
12 files changed, 810 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..4c09ed564 --- /dev/null +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js @@ -0,0 +1,162 @@ +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 = { + balance: PropTypes.string, + conversionRate: PropTypes.number, + convertedCurrency: PropTypes.string, + gasFeeError: PropTypes.bool, + gasLoadingError: PropTypes.bool, + gasTotal: PropTypes.string, + maxModeOn: PropTypes.bool, + showCustomizeGasModal: PropTypes.func, + selectedToken: PropTypes.object, + setAmountToMax: PropTypes.func, + setGasPrice: PropTypes.func, + setGasLimit: PropTypes.func, + tokenBalance: PropTypes.string, + 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> + } + + setMaxAmount () { + const { + balance, + gasTotal, + selectedToken, + setAmountToMax, + tokenBalance, + } = this.props + + setAmountToMax({ + balance, + gasTotal, + selectedToken, + tokenBalance, + }) + } + + renderContent () { + const { + conversionRate, + convertedCurrency, + gasLoadingError, + gasTotal, + showCustomizeGasModal, + gasPriceButtonGroupProps, + gasButtonGroupShown, + advancedInlineGasShown, + maxModeOn, + 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={async (...args) => { + metricsEvent({ + eventOpts: { + category: 'Transactions', + action: 'Edit Screen', + name: 'Changed Gas Button', + }, + }) + await gasPriceButtonGroupProps.handleGasPriceSelection(...args) + if (maxModeOn) { + this.setMaxAmount() + } + }} + /> + { this.renderAdvancedOptionsButton() } + </div> + const gasFeeDisplay = <GasFeeDisplay + conversionRate={conversionRate} + convertedCurrency={convertedCurrency} + gasLoadingError={gasLoadingError} + gasTotal={gasTotal} + onReset={() => { + resetGasButtons() + if (maxModeOn) { + this.setMaxAmount() + } + }} + 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..10eaa50b8 --- /dev/null +++ b/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js @@ -0,0 +1,134 @@ +import { connect } from 'react-redux' +import { + getConversionRate, + getCurrentCurrency, + getGasTotal, + getGasPrice, + getGasLimit, + getSendAmount, + getSendFromBalance, + getTokenBalance, +} from '../../send.selectors.js' +import { + getMaxModeOn, +} from '../send-amount-row/amount-max-button/amount-max-button.selectors' +import { + isBalanceSufficient, + calcGasTotal, +} from '../../send.utils.js' +import { calcMaxAmount } from '../send-amount-row/amount-max-button/amount-max-button.utils' +import { + getBasicGasEstimateLoadingStatus, + getRenderableEstimateDataForSmallButtonsFromGWEI, + getDefaultActiveButtonIndex, +} from '../../../../selectors/custom-gas' +import { + showGasButtonGroup, + updateSendErrors, +} 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, updateSendAmount } 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 { + balance: getSendFromBalance(state), + 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, + maxModeOn: getMaxModeOn(state), + selectedToken: getSelectedToken(state), + tokenBalance: getTokenBalance(state), + } +} + +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))) + } + }, + setAmountToMax: maxAmountDataObject => { + dispatch(updateSendErrors({ amount: null })) + dispatch(updateSendAmount(calcMaxAmount(maxAmountDataObject))) + }, + 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..4acb310f8 --- /dev/null +++ b/ui/app/pages/send/send-content/send-gas-row/tests/send-gas-row-container.test.js @@ -0,0 +1,209 @@ +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}`, + getSendFromBalance: (s) => `mockBalance:${s}`, + getTokenBalance: (s) => `mockTokenBalance:${s}`, + }, + '../send-amount-row/amount-max-button/amount-max-button.selectors': { + getMaxModeOn: (s) => `mockMaxModeOn:${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'), { + balance: 'mockBalance: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, + maxModeOn: 'mockMaxModeOn:mockState', + selectedToken: false, + tokenBalance: 'mockTokenBalance:mockState', + }) + }) + + }) + + 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') + }) + }) + +}) |