From 30a2be85eebe4f6b8cddb297f14faba392fe1133 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 13 Dec 2018 18:19:36 -0800 Subject: Prevent users from changing the From field in the send screen (#5922) * Prevent users from changing the From field in the send screen * Fix integration tests --- ui/app/actions.js | 8 -- .../account-list-item.component.js | 2 +- .../send/account-list-item/account-list-item.scss | 0 .../send/send-content/send-content-README.md | 0 .../send/send-content/send-content.component.js | 2 +- .../components/send/send-content/send-content.scss | 0 .../from-dropdown/from-dropdown-README.md | 0 .../from-dropdown/from-dropdown.component.js | 46 --------- .../send-from-row/from-dropdown/from-dropdown.scss | 0 .../send-from-row/from-dropdown/index.js | 1 - .../tests/from-dropdown-component.test.js | 88 ---------------- .../send-from-row/send-from-row-README.md | 0 .../send-from-row/send-from-row.component.js | 51 ++-------- .../send-from-row/send-from-row.container.js | 39 +------ .../tests/send-from-row-component.test.js | 112 ++------------------- .../tests/send-from-row-container.test.js | 86 +--------------- .../send-row-wrapper/send-row-wrapper.component.js | 8 +- ui/app/ducks/send.duck.js | 8 -- ui/app/ducks/tests/send-duck.test.js | 16 --- 19 files changed, 27 insertions(+), 440 deletions(-) delete mode 100644 ui/app/components/send/account-list-item/account-list-item.scss delete mode 100644 ui/app/components/send/send-content/send-content-README.md delete mode 100644 ui/app/components/send/send-content/send-content.scss delete mode 100644 ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown-README.md delete mode 100644 ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js delete mode 100644 ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.scss delete mode 100644 ui/app/components/send/send-content/send-from-row/from-dropdown/index.js delete mode 100644 ui/app/components/send/send-content/send-from-row/from-dropdown/tests/from-dropdown-component.test.js delete mode 100644 ui/app/components/send/send-content/send-from-row/send-from-row-README.md (limited to 'ui/app') diff --git a/ui/app/actions.js b/ui/app/actions.js index e1bb6dc2d..5a4389d67 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -202,7 +202,6 @@ var actions = { setGasTotal, setSendTokenBalance, updateSendTokenBalance, - updateSendFrom, updateSendHexData, updateSendTo, updateSendAmount, @@ -1008,13 +1007,6 @@ function setSendTokenBalance (tokenBalance) { } } -function updateSendFrom (from) { - return { - type: actions.UPDATE_SEND_FROM, - value: from, - } -} - function updateSendHexData (value) { return { type: actions.UPDATE_SEND_HEX_DATA, diff --git a/ui/app/components/send/account-list-item/account-list-item.component.js b/ui/app/components/send/account-list-item/account-list-item.component.js index 14bb7471f..a61467bb3 100644 --- a/ui/app/components/send/account-list-item/account-list-item.component.js +++ b/ui/app/components/send/account-list-item/account-list-item.component.js @@ -36,7 +36,7 @@ export default class AccountListItem extends Component { return (
handleClick({ name, address, balance })} + onClick={() => handleClick && handleClick({ name, address, balance })} >
diff --git a/ui/app/components/send/account-list-item/account-list-item.scss b/ui/app/components/send/account-list-item/account-list-item.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/ui/app/components/send/send-content/send-content-README.md b/ui/app/components/send/send-content/send-content-README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/ui/app/components/send/send-content/send-content.component.js b/ui/app/components/send/send-content/send-content.component.js index 1b03ffd2b..c780c88f5 100644 --- a/ui/app/components/send/send-content/send-content.component.js +++ b/ui/app/components/send/send-content/send-content.component.js @@ -13,7 +13,7 @@ export default class SendContent extends Component { updateGas: PropTypes.func, scanQrCode: PropTypes.func, showHexData: PropTypes.bool, - }; + } updateGas = (updateData) => this.props.updateGas(updateData) diff --git a/ui/app/components/send/send-content/send-content.scss b/ui/app/components/send/send-content/send-content.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown-README.md b/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown-README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js b/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js deleted file mode 100644 index d512f7d0b..000000000 --- a/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.component.js +++ /dev/null @@ -1,46 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import AccountListItem from '../../../account-list-item/' -import SendDropdownList from '../../send-dropdown-list/' - -export default class FromDropdown extends Component { - - static propTypes = { - accounts: PropTypes.array, - closeDropdown: PropTypes.func, - dropdownOpen: PropTypes.bool, - onSelect: PropTypes.func, - openDropdown: PropTypes.func, - selectedAccount: PropTypes.object, - } - - static contextTypes = { - t: PropTypes.func, - } - - render () { - const { - accounts, - closeDropdown, - dropdownOpen, - openDropdown, - selectedAccount, - onSelect, - } = this.props - - return
- } - /> - {dropdownOpen && } -
- } - -} diff --git a/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.scss b/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/ui/app/components/send/send-content/send-from-row/from-dropdown/index.js b/ui/app/components/send/send-content/send-from-row/from-dropdown/index.js deleted file mode 100644 index 2314ef4e3..000000000 --- a/ui/app/components/send/send-content/send-from-row/from-dropdown/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './from-dropdown.component' diff --git a/ui/app/components/send/send-content/send-from-row/from-dropdown/tests/from-dropdown-component.test.js b/ui/app/components/send/send-content/send-from-row/from-dropdown/tests/from-dropdown-component.test.js deleted file mode 100644 index 84fcb281e..000000000 --- a/ui/app/components/send/send-content/send-from-row/from-dropdown/tests/from-dropdown-component.test.js +++ /dev/null @@ -1,88 +0,0 @@ -import React from 'react' -import assert from 'assert' -import { shallow } from 'enzyme' -import sinon from 'sinon' -import FromDropdown from '../from-dropdown.component.js' - -import AccountListItem from '../../../../account-list-item/account-list-item.container' -import SendDropdownList from '../../../send-dropdown-list/send-dropdown-list.component' - -const propsMethodSpies = { - closeDropdown: sinon.spy(), - openDropdown: sinon.spy(), - onSelect: sinon.spy(), -} - -describe('FromDropdown Component', function () { - let wrapper - - beforeEach(() => { - wrapper = shallow(, { context: { t: str => str + '_t' } }) - }) - - afterEach(() => { - propsMethodSpies.closeDropdown.resetHistory() - propsMethodSpies.openDropdown.resetHistory() - propsMethodSpies.onSelect.resetHistory() - }) - - describe('render', () => { - it('should render a div with a .send-v2__from-dropdown class', () => { - assert.equal(wrapper.find('.send-v2__from-dropdown').length, 1) - }) - - it('should render an AccountListItem as the first child of the .send-v2__from-dropdown div', () => { - assert(wrapper.find('.send-v2__from-dropdown').childAt(0).is(AccountListItem)) - }) - - it('should pass the correct props to AccountListItem', () => { - const { - account, - handleClick, - icon, - } = wrapper.find('.send-v2__from-dropdown').childAt(0).props() - assert.deepEqual(account, { address: 'mockAddress' }) - assert.deepEqual( - icon, - - ) - assert.equal(propsMethodSpies.openDropdown.callCount, 0) - handleClick() - assert.equal(propsMethodSpies.openDropdown.callCount, 1) - }) - - it('should not render a SendDropdownList when dropdownOpen is false', () => { - assert.equal(wrapper.find(SendDropdownList).length, 0) - }) - - it('should render a SendDropdownList when dropdownOpen is true', () => { - wrapper.setProps({ dropdownOpen: true }) - assert(wrapper.find(SendDropdownList).length, 1) - }) - - it('should pass the correct props to the SendDropdownList]', () => { - wrapper.setProps({ dropdownOpen: true }) - const { - accounts, - closeDropdown, - onSelect, - activeAddress, - } = wrapper.find(SendDropdownList).props() - assert.deepEqual(accounts, ['mockAccount']) - assert.equal(activeAddress, 'mockAddress') - assert.equal(propsMethodSpies.closeDropdown.callCount, 0) - closeDropdown() - assert.equal(propsMethodSpies.closeDropdown.callCount, 1) - assert.equal(propsMethodSpies.onSelect.callCount, 0) - onSelect() - assert.equal(propsMethodSpies.onSelect.callCount, 1) - }) - }) -}) diff --git a/ui/app/components/send/send-content/send-from-row/send-from-row-README.md b/ui/app/components/send/send-content/send-from-row/send-from-row-README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/ui/app/components/send/send-content/send-from-row/send-from-row.component.js b/ui/app/components/send/send-content/send-from-row/send-from-row.component.js index b6de9d222..f8aa084d8 100644 --- a/ui/app/components/send/send-content/send-from-row/send-from-row.component.js +++ b/ui/app/components/send/send-content/send-from-row/send-from-row.component.js @@ -1,64 +1,27 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import SendRowWrapper from '../send-row-wrapper/' -import FromDropdown from './from-dropdown/' +import AccountListItem from '../../account-list-item' export default class SendFromRow extends Component { - static propTypes = { - closeFromDropdown: PropTypes.func, - conversionRate: PropTypes.number, from: PropTypes.object, - fromAccounts: PropTypes.array, - fromDropdownOpen: PropTypes.bool, - openFromDropdown: PropTypes.func, - tokenContract: PropTypes.object, - updateSendFrom: PropTypes.func, - setSendTokenBalance: PropTypes.func, } static contextTypes = { t: PropTypes.func, } - async handleFromChange (newFrom) { - const { - updateSendFrom, - tokenContract, - setSendTokenBalance, - } = this.props - - if (tokenContract) { - const usersToken = await tokenContract.balanceOf(newFrom.address) - setSendTokenBalance(usersToken) - } - - updateSendFrom(newFrom) - } - render () { - const { - closeFromDropdown, - conversionRate, - from, - fromAccounts, - fromDropdownOpen, - openFromDropdown, - } = this.props + const { t } = this.context + const { from } = this.props return ( - - closeFromDropdown()} - conversionRate={conversionRate} - dropdownOpen={fromDropdownOpen} - onSelect={newFrom => this.handleFromChange(newFrom)} - openDropdown={() => openFromDropdown()} - selectedAccount={from} - /> + +
+ +
) } - } diff --git a/ui/app/components/send/send-content/send-from-row/send-from-row.container.js b/ui/app/components/send/send-content/send-from-row/send-from-row.container.js index 7008bbea4..fe3ac9aa1 100644 --- a/ui/app/components/send/send-content/send-from-row/send-from-row.container.js +++ b/ui/app/components/send/send-content/send-from-row/send-from-row.container.js @@ -1,46 +1,11 @@ import { connect } from 'react-redux' -import { - accountsWithSendEtherInfoSelector, - getConversionRate, - getSelectedTokenContract, - getSendFromObject, -} from '../../send.selectors.js' -import { - getFromDropdownOpen, -} from './send-from-row.selectors.js' -import { calcTokenBalance } from '../../send.utils.js' -import { - updateSendFrom, - setSendTokenBalance, -} from '../../../../actions' -import { - closeFromDropdown, - openFromDropdown, -} from '../../../../ducks/send.duck' +import { getSendFromObject } from '../../send.selectors.js' import SendFromRow from './send-from-row.component' -export default connect(mapStateToProps, mapDispatchToProps)(SendFromRow) - function mapStateToProps (state) { return { - conversionRate: getConversionRate(state), from: getSendFromObject(state), - fromAccounts: accountsWithSendEtherInfoSelector(state), - fromDropdownOpen: getFromDropdownOpen(state), - tokenContract: getSelectedTokenContract(state), } } -function mapDispatchToProps (dispatch) { - return { - closeFromDropdown: () => dispatch(closeFromDropdown()), - openFromDropdown: () => dispatch(openFromDropdown()), - updateSendFrom: newFrom => dispatch(updateSendFrom(newFrom)), - setSendTokenBalance: (usersToken, selectedToken) => { - if (!usersToken) return - - const tokenBalance = calcTokenBalance({ usersToken, selectedToken }) - dispatch(setSendTokenBalance(tokenBalance)) - }, - } -} +export default connect(mapStateToProps)(SendFromRow) diff --git a/ui/app/components/send/send-content/send-from-row/tests/send-from-row-component.test.js b/ui/app/components/send/send-content/send-from-row/tests/send-from-row-component.test.js index 9ba8d1739..18811c57e 100644 --- a/ui/app/components/send/send-content/send-from-row/tests/send-from-row-component.test.js +++ b/ui/app/components/send/send-content/send-from-row/tests/send-from-row-component.test.js @@ -1,121 +1,31 @@ import React from 'react' import assert from 'assert' import { shallow } from 'enzyme' -import sinon from 'sinon' import SendFromRow from '../send-from-row.component.js' - +import AccountListItem from '../../../account-list-item' import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component' -import FromDropdown from '../from-dropdown/from-dropdown.component' - -const propsMethodSpies = { - closeFromDropdown: sinon.spy(), - openFromDropdown: sinon.spy(), - updateSendFrom: sinon.spy(), - setSendTokenBalance: sinon.spy(), -} - -sinon.spy(SendFromRow.prototype, 'handleFromChange') describe('SendFromRow Component', function () { - let wrapper - let instance - - beforeEach(() => { - wrapper = shallow(, { context: { t: str => str + '_t' } }) - instance = wrapper.instance() - }) - - afterEach(() => { - propsMethodSpies.closeFromDropdown.resetHistory() - propsMethodSpies.openFromDropdown.resetHistory() - propsMethodSpies.updateSendFrom.resetHistory() - propsMethodSpies.setSendTokenBalance.resetHistory() - SendFromRow.prototype.handleFromChange.resetHistory() - }) - - describe('handleFromChange', () => { - - it('should call updateSendFrom', () => { - assert.equal(propsMethodSpies.updateSendFrom.callCount, 0) - instance.handleFromChange('mockFrom') - assert.equal(propsMethodSpies.updateSendFrom.callCount, 1) - assert.deepEqual( - propsMethodSpies.updateSendFrom.getCall(0).args, - ['mockFrom'] - ) - }) - - it('should call tokenContract.balanceOf and setSendTokenBalance if tokenContract is defined', async () => { - wrapper.setProps({ - tokenContract: { - balanceOf: () => new Promise((resolve) => resolve('mockUsersToken')), - }, - }) - assert.equal(propsMethodSpies.setSendTokenBalance.callCount, 0) - await instance.handleFromChange('mockFrom') - assert.equal(propsMethodSpies.setSendTokenBalance.callCount, 1) - assert.deepEqual( - propsMethodSpies.setSendTokenBalance.getCall(0).args, - ['mockUsersToken'] - ) - }) - - }) - describe('render', () => { + const wrapper = shallow( + , + { context: { t: str => str + '_t' } } + ) + it('should render a SendRowWrapper component', () => { assert.equal(wrapper.find(SendRowWrapper).length, 1) }) it('should pass the correct props to SendRowWrapper', () => { - const { - label, - } = wrapper.find(SendRowWrapper).props() - + const { label } = wrapper.find(SendRowWrapper).props() assert.equal(label, 'from_t:') }) - it('should render an FromDropdown as a child of the SendRowWrapper', () => { - assert(wrapper.find(SendRowWrapper).childAt(0).is(FromDropdown)) - }) - it('should render the FromDropdown with the correct props', () => { - const { - accounts, - closeDropdown, - conversionRate, - dropdownOpen, - onSelect, - openDropdown, - selectedAccount, - } = wrapper.find(SendRowWrapper).childAt(0).props() - assert.deepEqual(accounts, ['mockAccount']) - assert.equal(dropdownOpen, false) - assert.equal(conversionRate, 15) - assert.deepEqual(selectedAccount, { address: 'mockAddress' }) - assert.equal(propsMethodSpies.closeFromDropdown.callCount, 0) - closeDropdown() - assert.equal(propsMethodSpies.closeFromDropdown.callCount, 1) - assert.equal(propsMethodSpies.openFromDropdown.callCount, 0) - openDropdown() - assert.equal(propsMethodSpies.openFromDropdown.callCount, 1) - assert.equal(SendFromRow.prototype.handleFromChange.callCount, 0) - onSelect('mockNewFrom') - assert.equal(SendFromRow.prototype.handleFromChange.callCount, 1) - assert.deepEqual( - SendFromRow.prototype.handleFromChange.getCall(0).args, - ['mockNewFrom'] - ) + const { account } = wrapper.find(AccountListItem).props() + assert.deepEqual(account, { address: 'mockAddress' }) }) }) }) diff --git a/ui/app/components/send/send-content/send-from-row/tests/send-from-row-container.test.js b/ui/app/components/send/send-content/send-from-row/tests/send-from-row-container.test.js index e080b2fe3..fd771ea77 100644 --- a/ui/app/components/send/send-content/send-from-row/tests/send-from-row-container.test.js +++ b/ui/app/components/send/send-content/send-from-row/tests/send-from-row-container.test.js @@ -1,110 +1,26 @@ import assert from 'assert' import proxyquire from 'proxyquire' -import sinon from 'sinon' let mapStateToProps -let mapDispatchToProps - -const actionSpies = { - updateSendFrom: sinon.spy(), - setSendTokenBalance: sinon.spy(), -} -const duckActionSpies = { - closeFromDropdown: sinon.spy(), - openFromDropdown: sinon.spy(), -} proxyquire('../send-from-row.container.js', { 'react-redux': { - connect: (ms, md) => { + connect: ms => { mapStateToProps = ms - mapDispatchToProps = md return () => ({}) }, }, '../../send.selectors.js': { - accountsWithSendEtherInfoSelector: (s) => `mockFromAccounts:${s}`, - getConversionRate: (s) => `mockConversionRate:${s}`, - getSelectedTokenContract: (s) => `mockTokenContract:${s}`, getSendFromObject: (s) => `mockFrom:${s}`, }, - './send-from-row.selectors.js': { getFromDropdownOpen: (s) => `mockFromDropdownOpen:${s}` }, - '../../send.utils.js': { calcTokenBalance: ({ usersToken, selectedToken }) => usersToken + selectedToken }, - '../../../../actions': actionSpies, - '../../../../ducks/send.duck': duckActionSpies, }) describe('send-from-row container', () => { - describe('mapStateToProps()', () => { - it('should map the correct properties to props', () => { assert.deepEqual(mapStateToProps('mockState'), { - conversionRate: 'mockConversionRate:mockState', from: 'mockFrom:mockState', - fromAccounts: 'mockFromAccounts:mockState', - fromDropdownOpen: 'mockFromDropdownOpen:mockState', - tokenContract: 'mockTokenContract:mockState', - }) - }) - - }) - - describe('mapDispatchToProps()', () => { - let dispatchSpy - let mapDispatchToPropsObject - - beforeEach(() => { - dispatchSpy = sinon.spy() - mapDispatchToPropsObject = mapDispatchToProps(dispatchSpy) - }) - - describe('closeFromDropdown()', () => { - it('should dispatch a closeFromDropdown action', () => { - mapDispatchToPropsObject.closeFromDropdown() - assert(dispatchSpy.calledOnce) - assert(duckActionSpies.closeFromDropdown.calledOnce) - assert.equal( - duckActionSpies.closeFromDropdown.getCall(0).args[0], - undefined - ) }) }) - - describe('openFromDropdown()', () => { - it('should dispatch a openFromDropdown action', () => { - mapDispatchToPropsObject.openFromDropdown() - assert(dispatchSpy.calledOnce) - assert(duckActionSpies.openFromDropdown.calledOnce) - assert.equal( - duckActionSpies.openFromDropdown.getCall(0).args[0], - undefined - ) - }) - }) - - describe('updateSendFrom()', () => { - it('should dispatch an updateSendFrom action', () => { - mapDispatchToPropsObject.updateSendFrom('mockFrom') - assert(dispatchSpy.calledOnce) - assert.equal( - actionSpies.updateSendFrom.getCall(0).args[0], - 'mockFrom' - ) - }) - }) - - describe('setSendTokenBalance()', () => { - it('should dispatch an setSendTokenBalance action', () => { - mapDispatchToPropsObject.setSendTokenBalance('mockUsersToken', 'mockSelectedToken') - assert(dispatchSpy.calledOnce) - assert.equal( - actionSpies.setSendTokenBalance.getCall(0).args[0], - 'mockUsersTokenmockSelectedToken' - ) - }) - }) - }) - }) diff --git a/ui/app/components/send/send-content/send-row-wrapper/send-row-wrapper.component.js b/ui/app/components/send/send-content/send-row-wrapper/send-row-wrapper.component.js index b7528a15f..04f4f8a15 100644 --- a/ui/app/components/send/send-content/send-row-wrapper/send-row-wrapper.component.js +++ b/ui/app/components/send/send-content/send-row-wrapper/send-row-wrapper.component.js @@ -29,12 +29,12 @@ export default class SendRowWrapper extends Component { return (
- {label} - {showError && } - {customLabelContent} + {label} + {showError && } + {customLabelContent}
- {formField} + {formField}
) diff --git a/ui/app/ducks/send.duck.js b/ui/app/ducks/send.duck.js index 758916d48..4d212bd03 100644 --- a/ui/app/ducks/send.duck.js +++ b/ui/app/ducks/send.duck.js @@ -62,14 +62,6 @@ export default function reducer ({ send: sendState = initState }, action = {}) { } // Action Creators -export function openFromDropdown () { - return { type: OPEN_FROM_DROPDOWN } -} - -export function closeFromDropdown () { - return { type: CLOSE_FROM_DROPDOWN } -} - export function openToDropdown () { return { type: OPEN_TO_DROPDOWN } } diff --git a/ui/app/ducks/tests/send-duck.test.js b/ui/app/ducks/tests/send-duck.test.js index 196fe226c..ffd8bfb4b 100644 --- a/ui/app/ducks/tests/send-duck.test.js +++ b/ui/app/ducks/tests/send-duck.test.js @@ -1,8 +1,6 @@ import assert from 'assert' import SendReducer, { - openFromDropdown, - closeFromDropdown, openToDropdown, closeToDropdown, updateSendErrors, @@ -140,20 +138,6 @@ describe('Send Duck', () => { }) }) - describe('openFromDropdown', () => { - assert.deepEqual( - openFromDropdown(), - { type: OPEN_FROM_DROPDOWN } - ) - }) - - describe('closeFromDropdown', () => { - assert.deepEqual( - closeFromDropdown(), - { type: CLOSE_FROM_DROPDOWN } - ) - }) - describe('openToDropdown', () => { assert.deepEqual( openToDropdown(), -- cgit v1.2.3