diff options
Diffstat (limited to 'ui/app/components/dropdowns')
7 files changed, 365 insertions, 9 deletions
diff --git a/ui/app/components/dropdowns/account-details-dropdown.js b/ui/app/components/dropdowns/account-details-dropdown.js new file mode 100644 index 000000000..7476cfdd9 --- /dev/null +++ b/ui/app/components/dropdowns/account-details-dropdown.js @@ -0,0 +1,109 @@ +const Component = require('react').Component +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const inherits = require('util').inherits +const connect = require('react-redux').connect +const actions = require('../../actions') +const { getSelectedIdentity } = require('../../selectors') +const genAccountLink = require('../../../lib/account-link.js') +const { Menu, Item, CloseArea } = require('./components/menu') + +AccountDetailsDropdown.contextTypes = { + t: PropTypes.func, +} + +module.exports = connect(mapStateToProps, mapDispatchToProps)(AccountDetailsDropdown) + +function mapStateToProps (state) { + return { + selectedIdentity: getSelectedIdentity(state), + network: state.metamask.network, + keyrings: state.metamask.keyrings, + } +} + +function mapDispatchToProps (dispatch) { + return { + showAccountDetailModal: () => { + dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) + }, + viewOnEtherscan: (address, network) => { + global.platform.openWindow({ url: genAccountLink(address, network) }) + }, + showRemoveAccountConfirmationModal: (identity) => { + return dispatch(actions.showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity })) + }, + } +} + +inherits(AccountDetailsDropdown, Component) +function AccountDetailsDropdown () { + Component.call(this) + + this.onClose = this.onClose.bind(this) +} + +AccountDetailsDropdown.prototype.onClose = function (e) { + e.stopPropagation() + this.props.onClose() +} + +AccountDetailsDropdown.prototype.render = function () { + const { + selectedIdentity, + network, + keyrings, + showAccountDetailModal, + viewOnEtherscan, + showRemoveAccountConfirmationModal } = this.props + + const address = selectedIdentity.address + + const keyring = keyrings.find((kr) => { + return kr.accounts.includes(address) + }) + + const isRemovable = keyring.type !== 'HD Key Tree' + + return h(Menu, { className: 'account-details-dropdown', isShowing: true }, [ + h(CloseArea, { + onClick: this.onClose, + }), + h(Item, { + onClick: (e) => { + e.stopPropagation() + global.platform.openExtensionInBrowser() + this.props.onClose() + }, + text: this.context.t('expandView'), + icon: h(`img`, { src: 'images/expand.svg', style: { height: '15px' } }), + }), + h(Item, { + onClick: (e) => { + e.stopPropagation() + showAccountDetailModal() + this.props.onClose() + }, + text: this.context.t('accountDetails'), + icon: h(`img`, { src: 'images/info.svg', style: { height: '15px' } }), + }), + h(Item, { + onClick: (e) => { + e.stopPropagation() + viewOnEtherscan(address, network) + this.props.onClose() + }, + text: this.context.t('viewOnEtherscan'), + icon: h(`img`, { src: 'images/open-etherscan.svg', style: { height: '15px' } }), + }), + isRemovable ? h(Item, { + onClick: (e) => { + e.stopPropagation() + showRemoveAccountConfirmationModal(selectedIdentity) + this.props.onClose() + }, + text: this.context.t('removeAccount'), + icon: h(`img`, { src: 'images/hide.svg', style: { height: '15px' } }), + }) : null, + ]) +} diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 63a30dd82..b252b25d9 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -43,6 +43,9 @@ function mapDispatchToProps (dispatch) { setRpcTarget: (target) => { dispatch(actions.setRpcTarget(target)) }, + delRpcTarget: (target) => { + dispatch(actions.delRpcTarget(target)) + }, showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()), hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), } @@ -300,6 +303,13 @@ NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) { color: currentRpcTarget ? '#ffffff' : '#9b9b9b', }, }, rpc), + h('i.fa.fa-times.delete', + { + onClick: (e) => { + e.stopPropagation() + props.delRpcTarget(rpc) + }, + }), ] ) } diff --git a/ui/app/components/dropdowns/tests/dropdown.test.js b/ui/app/components/dropdowns/tests/dropdown.test.js new file mode 100644 index 000000000..2b026589a --- /dev/null +++ b/ui/app/components/dropdowns/tests/dropdown.test.js @@ -0,0 +1,37 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { shallow } from 'enzyme' +import { DropdownMenuItem } from '../components/dropdown.js' + +describe('', () => { + let wrapper + const onClickSpy = sinon.spy() + const closeMenuSpy = sinon.spy() + + beforeEach(() => { + wrapper = shallow( + <DropdownMenuItem + onClick = {onClickSpy} + style = {{test: 'style'}} + closeMenu = {closeMenuSpy} + > + </DropdownMenuItem> + ) + }) + + it('renders li with dropdown-menu-item class', () => { + assert.equal(wrapper.find('li.dropdown-menu-item').length, 1) + }) + + it('adds style based on props passed', () => { + assert.equal(wrapper.prop('style').test, 'style') + }) + + it('simulates click event and calls onClick and closeMenu', () => { + wrapper.prop('onClick')() + assert.equal(onClickSpy.callCount, 1) + assert.equal(closeMenuSpy.callCount, 1) + }) + +}) diff --git a/ui/app/components/dropdowns/tests/menu.test.js b/ui/app/components/dropdowns/tests/menu.test.js new file mode 100644 index 000000000..9f5f13f00 --- /dev/null +++ b/ui/app/components/dropdowns/tests/menu.test.js @@ -0,0 +1,87 @@ +import React from 'react' +import assert from 'assert' +import sinon from 'sinon' +import { shallow } from 'enzyme' +import { Menu, Item, Divider, CloseArea } from '../components/menu' + +describe('Dropdown Menu Components', () => { + + describe('Menu', () => { + let wrapper + + beforeEach(() => { + wrapper = shallow( + <Menu className = {'Test Class'} isShowing = {true}/> + ) + }) + + it('adds prop className to menu', () => { + assert.equal(wrapper.find('.menu').prop('className'), 'menu Test Class') + }) + + }) + + describe('Item', () => { + let wrapper + + const onClickSpy = sinon.spy() + + beforeEach(() => { + wrapper = shallow( + <Item + icon = {'test icon'} + text = {'test text'} + className = {'test className'} + onClick = {onClickSpy} + /> + ) + }) + + it('add className based on props', () => { + assert.equal(wrapper.find('.menu__item').prop('className'), 'menu__item menu__item test className menu__item--clickable') + }) + + it('simulates onClick called', () => { + wrapper.find('.menu__item').prop('onClick')() + assert.equal(onClickSpy.callCount, 1) + }) + + it('adds icon based on icon props', () => { + assert.equal(wrapper.find('.menu__item__icon').text(), 'test icon') + }) + + it('adds html text based on text props', () => { + assert.equal(wrapper.find('.menu__item__text').text(), 'test text') + }) + }) + + describe('Divider', () => { + let wrapper + + before(() => { + wrapper = shallow(<Divider />) + }) + + it('renders menu divider', () => { + assert.equal(wrapper.find('.menu__divider').length, 1) + }) + }) + + describe('CloseArea', () => { + let wrapper + + const onClickSpy = sinon.spy() + + beforeEach(() => { + wrapper = shallow(<CloseArea + onClick = {onClickSpy} + />) + }) + + it('simulates click', () => { + wrapper.prop('onClick')() + assert.equal(onClickSpy.callCount, 1) + }) + }) + +}) diff --git a/ui/app/components/dropdowns/tests/network-dropdown-icon.test.js b/ui/app/components/dropdowns/tests/network-dropdown-icon.test.js new file mode 100644 index 000000000..67b192c11 --- /dev/null +++ b/ui/app/components/dropdowns/tests/network-dropdown-icon.test.js @@ -0,0 +1,25 @@ +import React from 'react' +import assert from 'assert' +import { shallow } from 'enzyme' +import NetworkDropdownIcon from '../components/network-dropdown-icon' + +describe('Network Dropdown Icon', () => { + let wrapper + + beforeEach(() => { + wrapper = shallow(<NetworkDropdownIcon + backgroundColor = {'red'} + isSelected = {false} + innerBorder = {'none'} + diameter = {'12'} + />) + }) + + it('adds style props based on props', () => { + const styleProp = wrapper.find('.menu-icon-circle').children().prop('style') + assert.equal(styleProp.background, 'red') + assert.equal(styleProp.border, 'none') + assert.equal(styleProp.height, '12px') + assert.equal(styleProp.width, '12px') + }) +}) diff --git a/ui/app/components/dropdowns/tests/network-dropdown.test.js b/ui/app/components/dropdowns/tests/network-dropdown.test.js new file mode 100644 index 000000000..699b54605 --- /dev/null +++ b/ui/app/components/dropdowns/tests/network-dropdown.test.js @@ -0,0 +1,97 @@ +import React from 'react' +import assert from 'assert' +import { createMockStore } from 'redux-test-utils' +import { mountWithRouter } from '../../../../../test/lib/render-helpers' +import NetworkDropdown from '../network-dropdown' +import { DropdownMenuItem } from '../components/dropdown' +import NetworkDropdownIcon from '../components/network-dropdown-icon' + +describe('Network Dropdown', () => { + let wrapper + + describe('NetworkDropdown in appState in false', () => { + const mockState = { + metamask: { + provider: { + type: 'test', + }, + }, + appState: { + networkDropdown: false, + }, + } + + const store = createMockStore(mockState) + + beforeEach(() => { + wrapper = mountWithRouter( + <NetworkDropdown store={store} /> + ) + }) + + it('checks for network droppo class', () => { + assert.equal(wrapper.find('.network-droppo').length, 1) + }) + + it('renders only one child when networkDropdown is false in state', () => { + assert.equal(wrapper.children().length, 1) + }) + + }) + + describe('NetworkDropdown in appState is true', () => { + const mockState = { + metamask: { + provider: { + 'type': 'test', + }, + frequentRpcList: [ + 'http://localhost:7545', + ], + }, + appState: { + 'networkDropdownOpen': true, + }, + } + const store = createMockStore(mockState) + + beforeEach(() => { + wrapper = mountWithRouter( + <NetworkDropdown store={store}/>, + ) + }) + + it('renders 7 DropDownMenuItems ', () => { + assert.equal(wrapper.find(DropdownMenuItem).length, 7) + }) + + it('checks background color for first NetworkDropdownIcon', () => { + assert.equal(wrapper.find(NetworkDropdownIcon).at(0).prop('backgroundColor'), '#29B6AF') // Main Ethereum Network Teal + }) + + it('checks background color for second NetworkDropdownIcon', () => { + assert.equal(wrapper.find(NetworkDropdownIcon).at(1).prop('backgroundColor'), '#ff4a8d') // Ropsten Red + }) + + it('checks background color for third NetworkDropdownIcon', () => { + assert.equal(wrapper.find(NetworkDropdownIcon).at(2).prop('backgroundColor'), '#7057ff') // Kovan Purple + }) + + it('checks background color for fourth NetworkDropdownIcon', () => { + assert.equal(wrapper.find(NetworkDropdownIcon).at(3).prop('backgroundColor'), '#f6c343') // Rinkeby Yellow + }) + + it('checks background color for fifth NetworkDropdownIcon', () => { + assert.equal(wrapper.find(NetworkDropdownIcon).at(4).prop('innerBorder'), '1px solid #9b9b9b') + }) + + it('checks dropdown for frequestRPCList from state ', () => { + assert.equal(wrapper.find(DropdownMenuItem).at(5).text(), '✓http://localhost:7545') + }) + + it('checks background color for sixth NetworkDropdownIcon', () => { + assert.equal(wrapper.find(NetworkDropdownIcon).at(5).prop('innerBorder'), '1px solid #9b9b9b') + }) + + }) +}) diff --git a/ui/app/components/dropdowns/token-menu-dropdown.js b/ui/app/components/dropdowns/token-menu-dropdown.js index 5a794c7c1..8a072b1bc 100644 --- a/ui/app/components/dropdowns/token-menu-dropdown.js +++ b/ui/app/components/dropdowns/token-menu-dropdown.js @@ -5,7 +5,6 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') const genAccountLink = require('etherscan-link').createAccountLink -const copyToClipboard = require('copy-to-clipboard') const { Menu, Item, CloseArea } = require('./components/menu') TokenMenuDropdown.contextTypes = { @@ -59,14 +58,6 @@ TokenMenuDropdown.prototype.render = function () { h(Item, { onClick: (e) => { e.stopPropagation() - copyToClipboard(this.props.token.address) - this.props.onClose() - }, - text: this.context.t('copyContractAddress'), - }), - h(Item, { - onClick: (e) => { - e.stopPropagation() const url = genAccountLink(this.props.token.address, this.props.network) global.platform.openWindow({ url }) this.props.onClose() |