diff options
author | Alexander Tseung <alextsg@users.noreply.github.com> | 2018-12-14 10:19:36 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-14 10:19:36 +0800 |
commit | 30a2be85eebe4f6b8cddb297f14faba392fe1133 (patch) | |
tree | 34cec0a1910e9e16bbed103d4b0f65f61724f8fb /ui/app/components/send/send-content | |
parent | 435fdae84ac49b1366b8737215d97bd82002dccf (diff) | |
download | tangerine-wallet-browser-30a2be85eebe4f6b8cddb297f14faba392fe1133.tar tangerine-wallet-browser-30a2be85eebe4f6b8cddb297f14faba392fe1133.tar.gz tangerine-wallet-browser-30a2be85eebe4f6b8cddb297f14faba392fe1133.tar.bz2 tangerine-wallet-browser-30a2be85eebe4f6b8cddb297f14faba392fe1133.tar.lz tangerine-wallet-browser-30a2be85eebe4f6b8cddb297f14faba392fe1133.tar.xz tangerine-wallet-browser-30a2be85eebe4f6b8cddb297f14faba392fe1133.tar.zst tangerine-wallet-browser-30a2be85eebe4f6b8cddb297f14faba392fe1133.zip |
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
Diffstat (limited to 'ui/app/components/send/send-content')
14 files changed, 26 insertions, 407 deletions
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 --- a/ui/app/components/send/send-content/send-content-README.md +++ /dev/null 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 --- a/ui/app/components/send/send-content/send-content.scss +++ /dev/null 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 --- a/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown-README.md +++ /dev/null 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 <div className="send-v2__from-dropdown"> - <AccountListItem - account={selectedAccount} - handleClick={openDropdown} - icon={<i className={`fa fa-caret-down fa-lg`} style={ { color: '#dedede' } }/>} - /> - {dropdownOpen && <SendDropdownList - accounts={accounts} - closeDropdown={closeDropdown} - onSelect={onSelect} - activeAddress={selectedAccount.address} - />} - </div> - } - -} 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 --- a/ui/app/components/send/send-content/send-from-row/from-dropdown/from-dropdown.scss +++ /dev/null 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(<FromDropdown - accounts={['mockAccount']} - closeDropdown={propsMethodSpies.closeDropdown} - dropdownOpen={false} - onSelect={propsMethodSpies.onSelect} - openDropdown={propsMethodSpies.openDropdown} - selectedAccount={ { address: 'mockAddress' } } - />, { 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, - <i className={`fa fa-caret-down fa-lg`} style={ { color: '#dedede' } }/> - ) - 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 --- a/ui/app/components/send/send-content/send-from-row/send-from-row-README.md +++ /dev/null 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 ( - <SendRowWrapper label={`${this.context.t('from')}:`}> - <FromDropdown - accounts={fromAccounts} - closeDropdown={() => closeFromDropdown()} - conversionRate={conversionRate} - dropdownOpen={fromDropdownOpen} - onSelect={newFrom => this.handleFromChange(newFrom)} - openDropdown={() => openFromDropdown()} - selectedAccount={from} - /> + <SendRowWrapper label={`${t('from')}:`}> + <div className="send-v2__from-dropdown"> + <AccountListItem account={from} /> + </div> </SendRowWrapper> ) } - } 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(<SendFromRow - closeFromDropdown={propsMethodSpies.closeFromDropdown} - conversionRate={15} - from={ { address: 'mockAddress' } } - fromAccounts={['mockAccount']} - fromDropdownOpen={false} - openFromDropdown={propsMethodSpies.openFromDropdown} - setSendTokenBalance={propsMethodSpies.setSendTokenBalance} - tokenContract={null} - updateSendFrom={propsMethodSpies.updateSendFrom} - />, { 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( + <SendFromRow + from={ { address: 'mockAddress' } } + />, + { 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 ( <div className="send-v2__form-row"> <div className="send-v2__form-label"> - {label} - {showError && <SendRowErrorMessage errorType={errorType}/>} - {customLabelContent} + {label} + {showError && <SendRowErrorMessage errorType={errorType}/>} + {customLabelContent} </div> <div className="send-v2__form-field"> - {formField} + {formField} </div> </div> ) |