1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

Consolidate send, onboarding selectors (#8501)

* reorganize & dedupe send selectors
This commit is contained in:
Erik Marks 2020-05-04 08:22:34 -07:00 committed by GitHub
parent eaa9f759f9
commit 898f8458a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 256 additions and 326 deletions

View File

@ -110,11 +110,6 @@ describe('Selectors', function () {
assert.equal(sendAmount, '1bc16d674ec80000')
})
it('#getSendMaxModeState', function () {
const sendMaxModeState = selectors.getSendMaxModeState(mockState)
assert.equal(sendMaxModeState, false)
})
it('#getCurrentCurrency', function () {
const currentCurrency = selectors.getCurrentCurrency(mockState)
assert.equal(currentCurrency, 'usd')

View File

@ -45,6 +45,7 @@ import {
} from '../../../../selectors'
import {
getTokenBalance,
getSendMaxModeState,
} from '../../../../pages/send/send.selectors'
import {
formatCurrency,
@ -64,7 +65,6 @@ import {
isBalanceSufficient,
} from '../../../../pages/send/send.utils'
import { addHexPrefix } from 'ethereumjs-util'
import { getMaxModeOn } from '../../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.selectors'
import { calcMaxAmount } from '../../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils'
const mapStateToProps = (state, ownProps) => {
@ -93,7 +93,7 @@ const mapStateToProps = (state, ownProps) => {
const customGasPrice = calcCustomGasPrice(customModalGasPriceInHex)
const maxModeOn = getMaxModeOn(state)
const maxModeOn = getSendMaxModeState(state)
const gasPrices = getEstimatedGasPrices(state)
const estimatedTimes = getEstimatedGasTimes(state)

View File

@ -1,14 +1,14 @@
import { connect } from 'react-redux'
import CurrencyInput from './currency-input.component'
import { ETH } from '../../../helpers/constants/common'
import { getMaxModeOn } from '../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.selectors'
import { getSendMaxModeState } from '../../../pages/send/send.selectors'
import { getIsMainnet, preferencesSelector } from '../../../selectors'
const mapStateToProps = (state) => {
const { metamask: { nativeCurrency, currentCurrency, conversionRate } } = state
const { showFiatInTestnets } = preferencesSelector(state)
const isMainnet = getIsMainnet(state)
const maxModeOn = getMaxModeOn(state)
const maxModeOn = getSendMaxModeState(state)
return {
nativeCurrency,

View File

@ -1,7 +1,7 @@
import { connect } from 'react-redux'
import EndOfFlow from './end-of-flow.component'
import { setCompletedOnboarding } from '../../../store/actions'
import { getOnboardingInitiator } from '../first-time-flow.selectors'
import { getOnboardingInitiator } from '../../../selectors'
const firstTimeFlowTypeNameMap = {
create: 'New Wallet Created',

View File

@ -1,6 +1,6 @@
import { connect } from 'react-redux'
import FirstTimeFlow from './first-time-flow.component'
import { getFirstTimeFlowTypeRoute } from './first-time-flow.selectors'
import { getFirstTimeFlowTypeRoute } from '../../selectors'
import {
createNewVaultAndGetSeedPhrase,
createNewVaultAndRestore,

View File

@ -1,7 +1,7 @@
import { connect } from 'react-redux'
import MetaMetricsOptIn from './metametrics-opt-in.component'
import { setParticipateInMetaMetrics } from '../../../store/actions'
import { getFirstTimeFlowTypeRoute } from '../first-time-flow.selectors'
import { getFirstTimeFlowTypeRoute } from '../../../selectors'
const firstTimeFlowTypeNameMap = {
create: 'Selected Create New Wallet',

View File

@ -4,7 +4,7 @@ import {
setCompletedOnboarding,
setSeedPhraseBackedUp,
} from '../../../../store/actions'
import { getOnboardingInitiator } from '../../first-time-flow.selectors'
import { getOnboardingInitiator } from '../../../../selectors'
const mapStateToProps = (state) => {
return {

View File

@ -2,7 +2,7 @@ import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import { compose } from 'redux'
import { setFirstTimeFlowType } from '../../../store/actions'
import { getFirstTimeFlowTypeRoute } from '../first-time-flow.selectors'
import { getFirstTimeFlowTypeRoute } from '../../../selectors'
import Welcome from './select-action.component'
const mapStateToProps = (state) => {

View File

@ -1,11 +0,0 @@
export function getToDropdownOpen (state) {
return state.send.toDropdownOpen
}
export function sendToIsInError (state) {
return Boolean(state.send.errors.to)
}
export function getTokens (state) {
return state.metamask.tokens
}

View File

@ -1,59 +0,0 @@
import assert from 'assert'
import {
getToDropdownOpen,
getTokens,
sendToIsInError,
} from '../add-recipient.selectors.js'
describe('add-recipient selectors', function () {
describe('getToDropdownOpen()', function () {
it('should return send.getToDropdownOpen', function () {
const state = {
send: {
toDropdownOpen: false,
},
}
assert.equal(getToDropdownOpen(state), false)
})
})
describe('sendToIsInError()', function () {
it('should return true if send.errors.to is truthy', function () {
const state = {
send: {
errors: {
to: 'abc',
},
},
}
assert.equal(sendToIsInError(state), true)
})
it('should return false if send.errors.to is falsy', function () {
const state = {
send: {
errors: {
to: null,
},
},
}
assert.equal(sendToIsInError(state), false)
})
})
describe('getTokens()', function () {
it('should return empty array if no tokens in state', function () {
const state = {
metamask: {
tokens: [],
},
}
assert.deepStrictEqual(getTokens(state), [])
})
})
})

View File

@ -4,9 +4,9 @@ import {
getSelectedToken,
getSendFromBalance,
getTokenBalance,
getSendMaxModeState,
} from '../../../send.selectors.js'
import { getBasicGasEstimateLoadingStatus } from '../../../../../selectors'
import { getMaxModeOn } from './amount-max-button.selectors.js'
import { calcMaxAmount } from './amount-max-button.utils.js'
import {
updateSendAmount,
@ -25,7 +25,7 @@ function mapStateToProps (state) {
balance: getSendFromBalance(state),
buttonDataLoading: getBasicGasEstimateLoadingStatus(state),
gasTotal: getGasTotal(state),
maxModeOn: getMaxModeOn(state),
maxModeOn: getSendMaxModeState(state),
selectedToken: getSelectedToken(state),
tokenBalance: getTokenBalance(state),
}

View File

@ -1,3 +0,0 @@
export function getMaxModeOn (state) {
return state.metamask.send.maxModeOn
}

View File

@ -26,8 +26,8 @@ proxyquire('../amount-max-button.container.js', {
getSelectedToken: (s) => `mockSelectedToken:${s}`,
getSendFromBalance: (s) => `mockBalance:${s}`,
getTokenBalance: (s) => `mockTokenBalance:${s}`,
getSendMaxModeState: (s) => `mockMaxModeOn:${s}`,
},
'./amount-max-button.selectors.js': { getMaxModeOn: (s) => `mockMaxModeOn:${s}` },
'./amount-max-button.utils.js': { calcMaxAmount: (mockObj) => mockObj.val + 1 },
'../../../../../selectors/': { getBasicGasEstimateLoadingStatus: (s) => `mockButtonDataLoading:${s}` },
'../../../../../store/actions': actionSpies,

View File

@ -1,22 +0,0 @@
import assert from 'assert'
import {
getMaxModeOn,
} from '../amount-max-button.selectors.js'
describe('amount-max-button selectors', function () {
describe('getMaxModeOn()', function () {
it('should', function () {
const state = {
metamask: {
send: {
maxModeOn: null,
},
},
}
assert.equal(getMaxModeOn(state), null)
})
})
})

View File

@ -9,10 +9,8 @@ import {
getSendFromBalance,
getTokenBalance,
getSendMaxModeState,
} from '../../send.selectors'
import {
sendAmountIsInError,
} from './send-amount-row.selectors'
} from '../../send.selectors'
import { getAmountErrorObject, getGasFeeErrorObject } from '../../send.utils'
import {
setMaxModeTo,

View File

@ -1,3 +0,0 @@
export function sendAmountIsInError (state) {
return Boolean(state.send.errors.amount)
}

View File

@ -19,7 +19,7 @@ proxyquire('../send-amount-row.container.js', {
return () => ({})
},
},
'./send-amount-row.selectors': { sendAmountIsInError: (s) => `mockInError:${s}` },
'../../send.selectors': { sendAmountIsInError: (s) => `mockInError:${s}` },
'../../send.utils': {
getAmountErrorObject: (mockDataObject) => ({ ...mockDataObject, mockChange: true }),
getGasFeeErrorObject: (mockDataObject) => ({ ...mockDataObject, mockGasFeeErrorChange: true }),

View File

@ -1,34 +0,0 @@
import assert from 'assert'
import {
sendAmountIsInError,
} from '../send-amount-row.selectors.js'
describe('send-amount-row selectors', function () {
describe('sendAmountIsInError()', function () {
it('should return true if send.errors.amount is truthy', function () {
const state = {
send: {
errors: {
amount: 'abc',
},
},
}
assert.equal(sendAmountIsInError(state), true)
})
it('should return false if send.errors.amount is falsy', function () {
const state = {
send: {
errors: {
amount: null,
},
},
}
assert.equal(sendAmountIsInError(state), false)
})
})
})

View File

@ -7,10 +7,11 @@ import {
getSendAmount,
getSendFromBalance,
getTokenBalance,
getSendMaxModeState,
getGasLoadingError,
gasFeeIsInError,
getGasButtonGroupShown,
} from '../../send.selectors.js'
import {
getMaxModeOn,
} from '../send-amount-row/amount-max-button/amount-max-button.selectors'
import {
isBalanceSufficient,
calcGasTotal,
@ -25,7 +26,6 @@ import {
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,
@ -73,7 +73,7 @@ function mapStateToProps (state) {
gasPrice,
gasLimit,
insufficientBalance,
maxModeOn: getMaxModeOn(state),
maxModeOn: getSendMaxModeState(state),
selectedToken: getSelectedToken(state),
tokenBalance: getTokenBalance(state),
}

View File

@ -1,11 +0,0 @@
export function getGasLoadingError (state) {
return state.send.errors.gasLoading
}
export function gasFeeIsInError (state) {
return Boolean(state.send.errors.gasFee)
}
export function getGasButtonGroupShown (state) {
return state.send.gasButtonGroupShown
}

View File

@ -30,8 +30,8 @@ proxyquire('../send-gas-row.container.js', {
return () => ({})
},
},
'../send-amount-row/amount-max-button/amount-max-button.selectors': {
getMaxModeOn: (s) => `mockMaxModeOn:${s}`,
'../../send.selectors.js': {
getSendMaxModeState: (s) => `mockMaxModeOn:${s}`,
},
'../../send.utils.js': {
isBalanceSufficient: ({

View File

@ -1,62 +0,0 @@
import assert from 'assert'
import {
gasFeeIsInError,
getGasLoadingError,
getGasButtonGroupShown,
} from '../send-gas-row.selectors.js'
describe('send-gas-row selectors', function () {
describe('getGasLoadingError()', function () {
it('should return send.errors.gasLoading', function () {
const state = {
send: {
errors: {
gasLoading: 'abc',
},
},
}
assert.equal(getGasLoadingError(state), 'abc')
})
})
describe('gasFeeIsInError()', function () {
it('should return true if send.errors.gasFee is truthy', function () {
const state = {
send: {
errors: {
gasFee: 'def',
},
},
}
assert.equal(gasFeeIsInError(state), true)
})
it('should return false send.errors.gasFee is falsely', function () {
const state = {
send: {
errors: {
gasFee: null,
},
},
}
assert.equal(gasFeeIsInError(state), false)
})
})
describe('getGasButtonGroupShown()', function () {
it('should return send.gasButtonGroupShown', function () {
const state = {
send: {
gasButtonGroupShown: 'foobar',
},
}
assert.equal(getGasButtonGroupShown(state), 'foobar')
})
})
})

View File

@ -22,10 +22,8 @@ import {
getTokenBalance,
getUnapprovedTxs,
getSendErrors,
} from '../send.selectors'
import {
isSendFormInError,
} from './send-footer.selectors'
} from '../send.selectors'
import {
addressIsNew,
constructTxParams,

View File

@ -1,5 +0,0 @@
import { getSendErrors } from '../send.selectors'
export function isSendFormInError (state) {
return Object.values(getSendErrors(state)).some((n) => n)
}

View File

@ -42,8 +42,8 @@ proxyquire('../send-footer.container.js', {
getSendHexData: (s) => `mockHexData:${s}`,
getUnapprovedTxs: (s) => `mockUnapprovedTxs:${s}`,
getSendErrors: (s) => `mockSendErrors:${s}`,
isSendFormInError: (s) => `mockInError:${s}`,
},
'./send-footer.selectors': { isSendFormInError: (s) => `mockInError:${s}` },
'./send-footer.utils': utilsStubs,
'../../../selectors/': {
getRenderableEstimateDataForSmallButtonsFromGWEI: (s) => ([{ gasEstimateType: `mockGasEstimateType:${s}` }]),

View File

@ -1,24 +0,0 @@
import assert from 'assert'
import proxyquire from 'proxyquire'
const {
isSendFormInError,
} = proxyquire('../send-footer.selectors', {
'../send.selectors': {
getSendErrors: (mockState) => mockState.errors,
},
})
describe('send-footer selectors', function () {
describe('getTitleKey()', function () {
it('should return true if any of the values of the object returned by getSendErrors are truthy', function () {
assert.equal(isSendFormInError({ errors: { a: 'abc', b: false } }), true)
})
it('should return false if all of the values of the object returned by getSendErrors are falsy', function () {
assert.equal(isSendFormInError({ errors: { a: false, b: null } }), false)
})
})
})

View File

@ -1,7 +1,7 @@
import { connect } from 'react-redux'
import { clearSend } from '../../../store/actions'
import SendHeader from './send-header.component'
import { getTitleKey } from './send-header.selectors'
import { getTitleKey } from '../send.selectors'
export default connect(mapStateToProps, mapDispatchToProps)(SendHeader)

View File

@ -1,18 +0,0 @@
import { getSelectedToken, getSendEditingTransactionId, getSendTo } from '../send.selectors.js'
export function getTitleKey (state) {
const isEditing = Boolean(getSendEditingTransactionId(state))
const isToken = Boolean(getSelectedToken(state))
if (!getSendTo(state)) {
return 'addRecipient'
}
if (isEditing) {
return 'edit'
} else if (isToken) {
return 'sendTokens'
} else {
return 'sendETH'
}
}

View File

@ -18,7 +18,7 @@ proxyquire('../send-header.container.js', {
},
},
'../../../store/actions': actionSpies,
'./send-header.selectors': {
'../send.selectors': {
getTitleKey: (s) => `mockTitleKey:${s}`,
},
})

View File

@ -1,34 +0,0 @@
import assert from 'assert'
import proxyquire from 'proxyquire'
const {
getTitleKey,
} = proxyquire('../send-header.selectors', {
'../send.selectors': {
getSelectedToken: (mockState) => mockState.t,
getSendEditingTransactionId: (mockState) => mockState.e,
getSendTo: (mockState) => mockState.to,
},
})
describe('send-header selectors', function () {
describe('getTitleKey()', function () {
it('should return the correct key when "to" is empty', function () {
assert.equal(getTitleKey({ e: 1, t: true, to: '' }), 'addRecipient')
})
it('should return the correct key when getSendEditingTransactionId is truthy', function () {
assert.equal(getTitleKey({ e: 1, t: true, to: '0x123' }), 'edit')
})
it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is truthy', function () {
assert.equal(getTitleKey({ e: null, t: 'abc', to: '0x123' }), 'sendTokens')
})
it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is falsy', function () {
assert.equal(getTitleKey({ e: null, to: '0x123' }), 'sendETH')
})
})
})

View File

@ -23,12 +23,12 @@ import {
getSendToNickname,
getTokenBalance,
getQrCodeData,
getTokens,
} from './send.selectors'
import {
getSelectedAddress,
getAddressBook,
} from '../../selectors'
import { getTokens } from './send-content/add-recipient/add-recipient.selectors'
import {
updateSendTo,
updateSendTokenBalance,

View File

@ -132,6 +132,10 @@ export function getSendErrors (state) {
return state.send.errors
}
export function sendAmountIsInError (state) {
return Boolean(state.send.errors.amount)
}
export function getSendFrom (state) {
return state.metamask.send.from
}
@ -192,3 +196,40 @@ export function getUnapprovedTxs (state) {
export function getQrCodeData (state) {
return state.appState.qrCodeData
}
export function getGasLoadingError (state) {
return state.send.errors.gasLoading
}
export function gasFeeIsInError (state) {
return Boolean(state.send.errors.gasFee)
}
export function getGasButtonGroupShown (state) {
return state.send.gasButtonGroupShown
}
export function getTokens (state) {
return state.metamask.tokens
}
export function getTitleKey (state) {
const isEditing = Boolean(getSendEditingTransactionId(state))
const isToken = Boolean(getSelectedToken(state))
if (!getSendTo(state)) {
return 'addRecipient'
}
if (isEditing) {
return 'edit'
} else if (isToken) {
return 'sendTokens'
} else {
return 'sendETH'
}
}
export function isSendFormInError (state) {
return Object.values(getSendErrors(state)).some((n) => n)
}

View File

@ -23,6 +23,7 @@ import {
getSelectedTokenExchangeRate,
getSelectedTokenToFiatRate,
getSendAmount,
sendAmountIsInError,
getSendEditingTransactionId,
getSendErrors,
getSendFrom,
@ -35,6 +36,12 @@ import {
getTokenBalance,
getTokenExchangeRate,
getUnapprovedTxs,
gasFeeIsInError,
getGasLoadingError,
getGasButtonGroupShown,
getTokens,
getTitleKey,
isSendFormInError,
} from '../send.selectors.js'
import mockState from './send-selectors-test-data'
@ -520,4 +527,184 @@ describe('send selectors', function () {
)
})
})
describe('send-amount-row selectors', function () {
describe('sendAmountIsInError()', function () {
it('should return true if send.errors.amount is truthy', function () {
const state = {
send: {
errors: {
amount: 'abc',
},
},
}
assert.equal(sendAmountIsInError(state), true)
})
it('should return false if send.errors.amount is falsy', function () {
const state = {
send: {
errors: {
amount: null,
},
},
}
assert.equal(sendAmountIsInError(state), false)
})
})
})
describe('send-gas-row selectors', function () {
describe('getGasLoadingError()', function () {
it('should return send.errors.gasLoading', function () {
const state = {
send: {
errors: {
gasLoading: 'abc',
},
},
}
assert.equal(getGasLoadingError(state), 'abc')
})
})
describe('gasFeeIsInError()', function () {
it('should return true if send.errors.gasFee is truthy', function () {
const state = {
send: {
errors: {
gasFee: 'def',
},
},
}
assert.equal(gasFeeIsInError(state), true)
})
it('should return false send.errors.gasFee is falsely', function () {
const state = {
send: {
errors: {
gasFee: null,
},
},
}
assert.equal(gasFeeIsInError(state), false)
})
})
describe('getGasButtonGroupShown()', function () {
it('should return send.gasButtonGroupShown', function () {
const state = {
send: {
gasButtonGroupShown: 'foobar',
},
}
assert.equal(getGasButtonGroupShown(state), 'foobar')
})
})
})
describe('add-recipient selectors', function () {
describe('getTokens()', function () {
it('should return empty array if no tokens in state', function () {
const state = {
metamask: {
tokens: [],
},
}
assert.deepStrictEqual(getTokens(state), [])
})
})
})
describe('send-header selectors', function () {
const getMetamaskSendMockState = (send) => {
return {
metamask: {
send: { ...send },
},
}
}
describe('getTitleKey()', function () {
it('should return the correct key when "to" is empty', function () {
assert.equal(getTitleKey(getMetamaskSendMockState({})), 'addRecipient')
})
it('should return the correct key when getSendEditingTransactionId is truthy', function () {
assert.equal(
getTitleKey(
getMetamaskSendMockState({
to: true,
editingTransactionId: true,
token: true, // this can be whatever
})
), 'edit')
})
it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is truthy', function () {
assert.equal(
getTitleKey(
getMetamaskSendMockState({
to: true,
editingTransactionId: false,
token: true,
})
), 'sendTokens')
})
it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is falsy', function () {
assert.equal(
getTitleKey(
getMetamaskSendMockState({
to: true,
editingTransactionId: false,
token: false,
})
), 'sendETH')
})
})
})
describe('send-footer selectors', function () {
const getSendMockState = (send) => {
return {
send: { ...send },
}
}
describe('isSendFormInError()', function () {
it('should return true if any of the values of the object returned by getSendErrors are truthy', function () {
assert.equal(isSendFormInError(
getSendMockState({
errors: [ true ],
})
), true)
})
it('should return false if all of the values of the object returned by getSendErrors are falsy', function () {
assert.equal(isSendFormInError(
getSendMockState({
errors: [],
})
), false)
assert.equal(isSendFormInError(
getSendMockState({
errors: [ false ],
})
), false)
})
})
})
})

View File

@ -2,7 +2,7 @@ import {
INITIALIZE_CREATE_PASSWORD_ROUTE,
INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE,
DEFAULT_ROUTE,
} from '../../helpers/constants/routes'
} from '../helpers/constants/routes'
export function getFirstTimeFlowTypeRoute (state) {
const { firstTimeFlowType } = state.metamask

View File

@ -1,5 +1,6 @@
export * from './confirm-transaction'
export * from './custom-gas'
export * from './first-time-flow'
export * from './permissions'
export * from './selectors'
export * from './tokens'

View File

@ -256,10 +256,6 @@ export function getSendAmount (state) {
return state.metamask.send.amount
}
export function getSendMaxModeState (state) {
return state.metamask.send.maxModeOn
}
export function getCurrentCurrency (state) {
return state.metamask.currentCurrency
}