diff options
Unit tests for from-dropdown; split out send-dropdown-list from from-dropdown
4 files changed, 260 insertions, 39 deletions
diff --git a/ui/app/components/send_/send-content/send-dropdown-list/send-dropdown-list.component.js b/ui/app/components/send_/send-content/send-dropdown-list/send-dropdown-list.component.js new file mode 100644 index 000000000..7bcc06c3e --- /dev/null +++ b/ui/app/components/send_/send-content/send-dropdown-list/send-dropdown-list.component.js @@ -0,0 +1,52 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import AccountListItem from '../../account-list-item/account-list-item.container' + +export default class SendDropdownList extends Component { + + static propTypes = { + accounts: PropTypes.array, + closeDropdown: PropTypes.func, + onSelect: PropTypes.func, + activeAddress: PropTypes.string, + }; + + getListItemIcon (accountAddress, activeAddress) { + return accountAddress === activeAddress + ? <i className={`fa fa-check fa-lg`} style={ { color: '#02c9b1' } }/> + : null + } + + render () { + const { + accounts, + closeDropdown, + onSelect, + activeAddress, + } = this.props + + return (<div> + <div + className="send-v2__from-dropdown__close-area" + onClick={() => closeDropdown()} + /> + <div className="send-v2__from-dropdown__list"> + {accounts.map((account, index) => <AccountListItem + account={account} + className="account-list-item__dropdown" + handleClick={() => { + onSelect(account) + closeDropdown() + }} + icon={this.getListItemIcon(account.address, activeAddress)} + key={`send-dropdown-account-#${index}`} + />)} + </div> + </div>) + } + +} + +SendDropdownList.contextTypes = { + t: PropTypes.func, +} diff --git a/ui/app/components/send_/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js b/ui/app/components/send_/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js new file mode 100644 index 000000000..44de529d4 --- /dev/null +++ b/ui/app/components/send_/send-content/send-dropdown-list/tests/send-dropdown-list-component.test.js @@ -0,0 +1,108 @@ +import React from 'react' +import assert from 'assert' +import { shallow } from 'enzyme' +import sinon from 'sinon' +import SendDropdownList from '../send-dropdown-list.component.js' + +import AccountListItem from '../../../account-list-item/account-list-item.container' + +const propsMethodSpies = { + closeDropdown: sinon.spy(), + onSelect: sinon.spy(), +} + +sinon.spy(SendDropdownList.prototype, 'getListItemIcon') + +describe('SendDropdownList Component', function () { + let wrapper + let instance + + beforeEach(() => { + wrapper = shallow(<SendDropdownList + accounts={[ + { address: 'mockAccount0' }, + { address: 'mockAccount1' }, + { address: 'mockAccount2' }, + ]} + closeDropdown={propsMethodSpies.closeDropdown} + onSelect={propsMethodSpies.onSelect} + activeAddress={'mockAddress2'} + />, { context: { t: str => str + '_t' } }) + instance = wrapper.instance() + }) + + afterEach(() => { + propsMethodSpies.closeDropdown.resetHistory() + propsMethodSpies.onSelect.resetHistory() + SendDropdownList.prototype.getListItemIcon.resetHistory() + }) + + describe('getListItemIcon', () => { + it('should return check icon if the passed addresses are the same', () => { + assert.deepEqual( + wrapper.instance().getListItemIcon('mockAccount0', 'mockAccount0'), + <i className={`fa fa-check fa-lg`} style={ { color: '#02c9b1' } }/> + ) + }) + + it('should return null if the passed addresses are different', () => { + assert.equal( + wrapper.instance().getListItemIcon('mockAccount0', 'mockAccount1'), + null + ) + }) + }) + + describe('render', () => { + it('should render a single div with two children', () => { + assert(wrapper.is('div')) + assert.equal(wrapper.children().length, 2) + }) + + it('should render the children with the correct classes', () => { + assert(wrapper.childAt(0).hasClass('send-v2__from-dropdown__close-area')) + assert(wrapper.childAt(1).hasClass('send-v2__from-dropdown__list')) + }) + + it('should call closeDropdown onClick of the send-v2__from-dropdown__close-area', () => { + assert.equal(propsMethodSpies.closeDropdown.callCount, 0) + wrapper.childAt(0).props().onClick() + assert.equal(propsMethodSpies.closeDropdown.callCount, 1) + }) + + it('should render an AccountListItem for each item in accounts', () => { + assert.equal(wrapper.childAt(1).children().length, 3) + assert(wrapper.childAt(1).children().every(AccountListItem)) + }) + + it('should pass the correct props to the AccountListItem', () => { + wrapper.childAt(1).children().forEach((accountListItem, index) => { + const { + account, + className, + handleClick, + icon, + } = accountListItem.props() + assert.deepEqual(account, { address: 'mockAccount' + index }) + assert.equal(className, 'account-list-item__dropdown') + assert.equal(propsMethodSpies.onSelect.callCount, 0) + handleClick() + assert.equal(propsMethodSpies.onSelect.callCount, 1) + assert.deepEqual(propsMethodSpies.onSelect.getCall(0).args[0], { address: 'mockAccount' + index }) + propsMethodSpies.onSelect.resetHistory() + propsMethodSpies.closeDropdown.resetHistory() + assert.equal(propsMethodSpies.closeDropdown.callCount, 0) + handleClick() + assert.equal(propsMethodSpies.closeDropdown.callCount, 1) + propsMethodSpies.onSelect.resetHistory() + propsMethodSpies.closeDropdown.resetHistory() + }) + }) + + it('should call this.getListItemIcon for each AccountListItem', () => { + assert.equal(SendDropdownList.prototype.getListItemIcon.callCount, 3) + const getListItemIconCalls = SendDropdownList.prototype.getListItemIcon.getCalls() + assert(getListItemIconCalls.every(({ args }, index) => args[0] === 'mockAccount' + index)) + }) + }) +}) 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 index 337228122..7815887a5 100644 --- 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 @@ -1,6 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import AccountListItem from '../../../account-list-item/account-list-item.container' +import SendDropdownList from '../../send-dropdown-list/send-dropdown-list.component' export default class FromDropdown extends Component { @@ -13,58 +14,28 @@ export default class FromDropdown extends Component { selectedAccount: PropTypes.object, }; - renderListItemIcon (icon, color) { - return <i className={`fa ${icon} fa-lg`} style={ { color } }/> - } - - getListItemIcon (currentAccount, selectedAccount) { - return currentAccount.address === selectedAccount.address - ? this.renderListItemIcon('fa-check', '#02c9b1') - : null - } - - renderDropdown () { + render () { const { accounts, closeDropdown, - onSelect, - selectedAccount, - } = this.props - - return (<div> - <div - className="send-v2__from-dropdown__close-area" - onClick={() => closeDropdown} - /> - <div className="send-v2__from-dropdown__list"> - {accounts.map((account, index) => <AccountListItem - account={account} - className="account-list-item__dropdown" - handleClick={() => { - onSelect(account) - closeDropdown() - }} - icon={this.getListItemIcon(account, selectedAccount.address)} - key={`from-dropdown-account-#${index}`} - />)} - </div> - </div>) - } - - render () { - const { dropdownOpen, openDropdown, selectedAccount, + onSelect, } = this.props return <div className="send-v2__from-dropdown"> <AccountListItem account={selectedAccount} handleClick={openDropdown} - icon={this.renderListItemIcon('fa-caret-down', '#dedede')} + icon={<i className={`fa fa-caret-down fa-lg`} style={ { color: '#dedede' } }/>} /> - {dropdownOpen && this.renderDropdown()}, + {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/tests/from-dropdown-component.test.js b/ui/app/components/send_/send-content/send-from-row/from-dropdown/tests/from-dropdown-component.test.js index e69de29bb..333775341 100644 --- 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 @@ -0,0 +1,90 @@ +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 + let instance + + 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' } }) + instance = wrapper.instance() + }) + + 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) + }) + }) +}) |