mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Various component tests and some conditional statements (#7765)
* Various component tests and some conditional statements Conditional in account-menu in removeAccount when keyring sometimes is not initially provideed Conditional on unlock-page when there is no target.getBoundingClientRect on the element. * Update helpers * Remove component debugging * Add default params for render helpers * Remove stubComponent for old Mascot Changes in https://github.com/MetaMask/metamask-extension/pull/7893 has prevented the need to stub it out. Change logout to lock in account-menu test
This commit is contained in:
parent
608a1fc298
commit
5d1c9313db
@ -56,6 +56,9 @@ require('jsdom-global')()
|
|||||||
// localStorage
|
// localStorage
|
||||||
window.localStorage = {}
|
window.localStorage = {}
|
||||||
|
|
||||||
|
// override metamask-logo
|
||||||
|
window.requestAnimationFrame = () => {}
|
||||||
|
|
||||||
// crypto.getRandomValues
|
// crypto.getRandomValues
|
||||||
if (!window.crypto) {
|
if (!window.crypto) {
|
||||||
window.crypto = {}
|
window.crypto = {}
|
||||||
|
@ -1,14 +1,7 @@
|
|||||||
import { shallow, mount } from 'enzyme'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { BrowserRouter } from 'react-router-dom'
|
import { mount } from 'enzyme'
|
||||||
import { shape } from 'prop-types'
|
import { MemoryRouter } from 'react-router-dom'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
export function shallowWithStore (component, store) {
|
|
||||||
const context = {
|
|
||||||
store,
|
|
||||||
}
|
|
||||||
return shallow(component, { context })
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mountWithStore (component, store) {
|
export function mountWithStore (component, store) {
|
||||||
const context = {
|
const context = {
|
||||||
@ -17,26 +10,40 @@ export function mountWithStore (component, store) {
|
|||||||
return mount(component, { context })
|
return mount(component, { context })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mountWithRouter (node) {
|
export function mountWithRouter (component, store = {}, pathname = '/') {
|
||||||
|
|
||||||
// Instantiate router context
|
// Instantiate router context
|
||||||
const router = {
|
const router = {
|
||||||
history: new BrowserRouter().history,
|
history: new MemoryRouter().history,
|
||||||
route: {
|
route: {
|
||||||
location: {},
|
location: {
|
||||||
|
pathname: pathname,
|
||||||
|
},
|
||||||
match: {},
|
match: {},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const createContext = () => ({
|
const createContext = () => ({
|
||||||
context: { router, t: () => {} },
|
context: {
|
||||||
childContextTypes: { router: shape({}), t: () => {} },
|
router,
|
||||||
|
t: str => str,
|
||||||
|
tOrKey: str => str,
|
||||||
|
metricsEvent: () => {},
|
||||||
|
store,
|
||||||
|
},
|
||||||
|
childContextTypes: {
|
||||||
|
router: PropTypes.object,
|
||||||
|
t: PropTypes.func,
|
||||||
|
tOrKey: PropTypes.func,
|
||||||
|
metricsEvent: PropTypes.func,
|
||||||
|
store: PropTypes.object,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const Wrapper = () => (
|
const Wrapper = () => (
|
||||||
<BrowserRouter>
|
<MemoryRouter initialEntries={[{ pathname }]} initialIndex={0}>
|
||||||
{node}
|
{component}
|
||||||
</BrowserRouter>
|
</MemoryRouter>
|
||||||
)
|
)
|
||||||
|
|
||||||
return mount(<Wrapper />, createContext())
|
return mount(<Wrapper />, createContext())
|
||||||
|
@ -193,6 +193,12 @@ export default class AccountMenu extends Component {
|
|||||||
|
|
||||||
renderRemoveAccount (keyring, identity) {
|
renderRemoveAccount (keyring, identity) {
|
||||||
const { t } = this.context
|
const { t } = this.context
|
||||||
|
|
||||||
|
// Sometimes keyrings aren't loaded yet
|
||||||
|
if (!keyring) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
// Any account that's not from the HD wallet Keyring can be removed
|
// Any account that's not from the HD wallet Keyring can be removed
|
||||||
const { type } = keyring
|
const { type } = keyring
|
||||||
const isRemovable = type !== 'HD Key Tree'
|
const isRemovable = type !== 'HD Key Tree'
|
||||||
|
209
ui/app/components/app/account-menu/tests/account-menu.test.js
Normal file
209
ui/app/components/app/account-menu/tests/account-menu.test.js
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import configureMockStore from 'redux-mock-store'
|
||||||
|
import { mountWithRouter } from '../../../../../../test/lib/render-helpers'
|
||||||
|
import AccountMenu from '../index'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
|
||||||
|
describe('Account Menu', async () => {
|
||||||
|
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const mockStore = {
|
||||||
|
metamask: {
|
||||||
|
provider: {
|
||||||
|
type: 'test',
|
||||||
|
},
|
||||||
|
preferences: {
|
||||||
|
useNativeCurrencyAsPrimaryCurrency: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = configureMockStore()(mockStore)
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
isAccountMenuOpen: true,
|
||||||
|
addressConnectedDomainMap: {},
|
||||||
|
accounts: [
|
||||||
|
{
|
||||||
|
address: '0xAddress',
|
||||||
|
name: 'Account 1',
|
||||||
|
balance: '0x0',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
address: '0xImportedAddress',
|
||||||
|
name: 'Imported Account 1',
|
||||||
|
balance: '0x0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
keyrings: [
|
||||||
|
{
|
||||||
|
type: 'HD Key Tree',
|
||||||
|
accounts: [
|
||||||
|
'0xAdress',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Simple Key Pair',
|
||||||
|
accounts: [
|
||||||
|
'0xImportedAddress',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
prevIsAccountMenuOpen: false,
|
||||||
|
lockMetamask: sinon.spy(),
|
||||||
|
showAccountDetail: sinon.spy(),
|
||||||
|
showRemoveAccountConfirmationModal: sinon.spy(),
|
||||||
|
toggleAccountMenu: sinon.spy(),
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
wrapper = mountWithRouter(
|
||||||
|
<Provider store={store}>
|
||||||
|
<AccountMenu.WrappedComponent {...props} />
|
||||||
|
</Provider>, store
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.toggleAccountMenu.resetHistory()
|
||||||
|
props.history.push.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Render Content', () => {
|
||||||
|
it('returns account name from identities', () => {
|
||||||
|
const accountName = wrapper.find('.account-menu__name')
|
||||||
|
assert.equal(accountName.length, 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders user preference currency display balance from account balance', () => {
|
||||||
|
const accountBalance = wrapper.find('.currency-display-component.account-menu__balance')
|
||||||
|
assert.equal(accountBalance.length, 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('simulate click', () => {
|
||||||
|
const click = wrapper.find('.account-menu__account.menu__item--clickable')
|
||||||
|
click.first().simulate('click')
|
||||||
|
|
||||||
|
assert(props.showAccountDetail.calledOnce)
|
||||||
|
assert.equal(props.showAccountDetail.getCall(0).args[0], '0xAddress')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('render imported account label', () => {
|
||||||
|
const importedAccount = wrapper.find('.keyring-label.allcaps')
|
||||||
|
assert.equal(importedAccount.text(), 'imported')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('remove account', () => {
|
||||||
|
const removeAccount = wrapper.find('.remove-account-icon')
|
||||||
|
removeAccount.simulate('click', {
|
||||||
|
preventDefault: () => {},
|
||||||
|
stopPropagation: () => {},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert(props.showRemoveAccountConfirmationModal.calledOnce)
|
||||||
|
assert.deepEqual(props.showRemoveAccountConfirmationModal.getCall(0).args[0],
|
||||||
|
{ address: '0xImportedAddress', balance: '0x0', name: 'Imported Account 1' }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Log Out', () => {
|
||||||
|
let logout
|
||||||
|
|
||||||
|
it('logout', () => {
|
||||||
|
logout = wrapper.find('.account-menu__lock-button')
|
||||||
|
assert.equal(logout.length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('simulate click', () => {
|
||||||
|
logout.simulate('click')
|
||||||
|
assert(props.lockMetamask.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Create Account', () => {
|
||||||
|
let createAccount
|
||||||
|
|
||||||
|
it('renders create account item', () => {
|
||||||
|
createAccount = wrapper.find({ text: 'createAccount' })
|
||||||
|
assert.equal(createAccount.length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls toggle menu and push new-account route to history', () => {
|
||||||
|
createAccount.simulate('click')
|
||||||
|
assert(props.toggleAccountMenu.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/new-account')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Import Account', () => {
|
||||||
|
let importAccount
|
||||||
|
|
||||||
|
it('renders import account item', () => {
|
||||||
|
importAccount = wrapper.find({ text: 'importAccount' })
|
||||||
|
assert.equal(importAccount.length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls toggle menu and push /new-account/import route to history', () => {
|
||||||
|
importAccount.simulate('click')
|
||||||
|
assert(props.toggleAccountMenu.calledOnce)
|
||||||
|
assert(props.history.push.getCall(0).args[0], '/new-account/import')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Connect Hardware Wallet', () => {
|
||||||
|
|
||||||
|
let connectHardwareWallet
|
||||||
|
|
||||||
|
it('renders import account item', () => {
|
||||||
|
connectHardwareWallet = wrapper.find({ text: 'connectHardwareWallet' })
|
||||||
|
assert.equal(connectHardwareWallet.length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls toggle menu and push /new-account/connect route to history', () => {
|
||||||
|
connectHardwareWallet.simulate('click')
|
||||||
|
assert(props.toggleAccountMenu.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/new-account/connect')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Info & Help', () => {
|
||||||
|
|
||||||
|
let infoHelp
|
||||||
|
|
||||||
|
it('renders import account item', () => {
|
||||||
|
infoHelp = wrapper.find({ text: 'infoHelp' })
|
||||||
|
assert.equal(infoHelp.length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls toggle menu and push /new-account/connect route to history', () => {
|
||||||
|
infoHelp.simulate('click')
|
||||||
|
assert(props.toggleAccountMenu.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/settings/about-us')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Settings', () => {
|
||||||
|
|
||||||
|
let settings
|
||||||
|
|
||||||
|
it('renders import account item', () => {
|
||||||
|
settings = wrapper.find({ text: 'settings' })
|
||||||
|
assert.equal(settings.length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls toggle menu and push /new-account/connect route to history', () => {
|
||||||
|
settings.simulate('click')
|
||||||
|
assert(props.toggleAccountMenu.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/settings')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
99
ui/app/components/app/app-header/tests/app-header.test.js
Normal file
99
ui/app/components/app/app-header/tests/app-header.test.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import MetaFoxLogo from '../../../ui/metafox-logo'
|
||||||
|
import AppHeader from '../index'
|
||||||
|
|
||||||
|
describe('App Header', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
hideNetworkDropdown: sinon.spy(),
|
||||||
|
showNetworkDropdown: sinon.spy(),
|
||||||
|
toggleAccountMenu: sinon.spy(),
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
network: 'test',
|
||||||
|
provider: {},
|
||||||
|
selectedAddress: '0xAddress',
|
||||||
|
disabled: false,
|
||||||
|
hideNetworkIndicator: false,
|
||||||
|
networkDropdownOpen: false,
|
||||||
|
isAccountMenuOpen: false,
|
||||||
|
isUnlocked: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(
|
||||||
|
<AppHeader.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
metricsEvent: () => {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.toggleAccountMenu.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('App Header Logo', () => {
|
||||||
|
it('routes to default route when logo is clicked', () => {
|
||||||
|
const appLogo = wrapper.find(MetaFoxLogo)
|
||||||
|
appLogo.simulate('click')
|
||||||
|
assert(props.history.push.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Network', () => {
|
||||||
|
it('shows network dropdown when networkDropdownOpen is false', () => {
|
||||||
|
const network = wrapper.find({ network: 'test' })
|
||||||
|
|
||||||
|
network.simulate('click', {
|
||||||
|
preventDefault: () => {},
|
||||||
|
stopPropagation: () => {},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert(props.showNetworkDropdown.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('hides network dropdown when networkDropdownOpen is true', () => {
|
||||||
|
wrapper.setProps({ networkDropdownOpen: true })
|
||||||
|
const network = wrapper.find({ network: 'test' })
|
||||||
|
|
||||||
|
network.simulate('click', {
|
||||||
|
preventDefault: () => {},
|
||||||
|
stopPropagation: () => {},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert(props.hideNetworkDropdown.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('hides network indicator', () => {
|
||||||
|
wrapper.setProps({ hideNetworkIndicator: true })
|
||||||
|
const network = wrapper.find({ network: 'test' })
|
||||||
|
assert.equal(network.length, 0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Account Menu', () => {
|
||||||
|
|
||||||
|
it('toggles account menu', () => {
|
||||||
|
const accountMenu = wrapper.find('.account-menu__icon')
|
||||||
|
accountMenu.simulate('click')
|
||||||
|
assert(props.toggleAccountMenu.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not toggle account menu when disabled', () => {
|
||||||
|
wrapper.setProps({ disabled: true })
|
||||||
|
const accountMenu = wrapper.find('.account-menu__icon')
|
||||||
|
accountMenu.simulate('click')
|
||||||
|
assert(props.toggleAccountMenu.notCalled)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
@ -40,7 +40,7 @@ class AccountDetailsDropdown extends Component {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
selectedIdentity: PropTypes.object.isRequired,
|
selectedIdentity: PropTypes.object.isRequired,
|
||||||
network: PropTypes.number.isRequired,
|
network: PropTypes.string.isRequired,
|
||||||
keyrings: PropTypes.array.isRequired,
|
keyrings: PropTypes.array.isRequired,
|
||||||
showAccountDetailModal: PropTypes.func.isRequired,
|
showAccountDetailModal: PropTypes.func.isRequired,
|
||||||
viewOnEtherscan: PropTypes.func.isRequired,
|
viewOnEtherscan: PropTypes.func.isRequired,
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import AdvancedTabContent from '../index'
|
||||||
|
|
||||||
|
describe('Advanced Gas Inputs', () => {
|
||||||
|
let wrapper, clock
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
updateCustomGasPrice: sinon.spy(),
|
||||||
|
updateCustomGasLimit: sinon.spy(),
|
||||||
|
showGasPriceInfoModal: sinon.spy(),
|
||||||
|
showGasLimitInfoModal: sinon.spy(),
|
||||||
|
customGasPrice: 0,
|
||||||
|
customGasLimit: 0,
|
||||||
|
insufficientBalance: false,
|
||||||
|
customPriceIsSafe: true,
|
||||||
|
isSpeedUp: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
clock = sinon.useFakeTimers()
|
||||||
|
|
||||||
|
wrapper = mount(
|
||||||
|
<AdvancedTabContent.WrappedComponent
|
||||||
|
{...props}
|
||||||
|
/>, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
clock.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('wont update gasPrice in props before debounce', () => {
|
||||||
|
const event = { target: { value: 1 } }
|
||||||
|
|
||||||
|
wrapper.find('input').at(0).simulate('change', event)
|
||||||
|
clock.tick(499)
|
||||||
|
|
||||||
|
assert.equal(props.updateCustomGasPrice.callCount, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('simulates onChange on gas price after debounce', () => {
|
||||||
|
const event = { target: { value: 1 } }
|
||||||
|
|
||||||
|
wrapper.find('input').at(0).simulate('change', event)
|
||||||
|
clock.tick(500)
|
||||||
|
|
||||||
|
assert.equal(props.updateCustomGasPrice.calledOnce, true)
|
||||||
|
assert.equal(props.updateCustomGasPrice.calledWith(1), true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('wont update gasLimit in props before debounce', () => {
|
||||||
|
const event = { target: { value: 21000 } }
|
||||||
|
|
||||||
|
wrapper.find('input').at(1).simulate('change', event)
|
||||||
|
clock.tick(499)
|
||||||
|
|
||||||
|
assert.equal(props.updateCustomGasLimit.callCount, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('simulates onChange on gas limit after debounce', () => {
|
||||||
|
const event = { target: { value: 21000 } }
|
||||||
|
|
||||||
|
wrapper.find('input').at(1).simulate('change', event)
|
||||||
|
clock.tick(500)
|
||||||
|
|
||||||
|
assert.equal(props.updateCustomGasLimit.calledOnce, true)
|
||||||
|
assert.equal(props.updateCustomGasLimit.calledWith(21000), true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('errors when insuffientBalance under gas price and gas limit', () => {
|
||||||
|
wrapper.setProps({ insufficientBalance: true })
|
||||||
|
const renderError = wrapper.find('.advanced-gas-inputs__gas-edit-row__error-text')
|
||||||
|
assert.equal(renderError.length, 2)
|
||||||
|
|
||||||
|
assert.equal(renderError.at(0).text(), 'insufficientBalance')
|
||||||
|
assert.equal(renderError.at(1).text(), 'insufficientBalance')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('errors zero gas price / speed up', () => {
|
||||||
|
wrapper.setProps({ isSpeedUp: true })
|
||||||
|
|
||||||
|
const renderError = wrapper.find('.advanced-gas-inputs__gas-edit-row__error-text')
|
||||||
|
assert.equal(renderError.length, 2)
|
||||||
|
|
||||||
|
assert.equal(renderError.at(0).text(), 'zeroGasPriceOnSpeedUpError')
|
||||||
|
assert.equal(renderError.at(1).text(), 'gasLimitTooLow')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('warns when custom gas price is too low', () => {
|
||||||
|
wrapper.setProps({ customPriceIsSafe: false })
|
||||||
|
|
||||||
|
const renderWarning = wrapper.find('.advanced-gas-inputs__gas-edit-row__warning-text')
|
||||||
|
assert.equal(renderWarning.length, 1)
|
||||||
|
|
||||||
|
assert.equal(renderWarning.text(), 'gasPriceExtremelyLow')
|
||||||
|
})
|
||||||
|
})
|
37
ui/app/components/app/info-box/tests/info-box.test.js
Normal file
37
ui/app/components/app/info-box/tests/info-box.test.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
|
||||||
|
import InfoBox from '../index'
|
||||||
|
|
||||||
|
describe('InfoBox', () => {
|
||||||
|
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
title: 'Title',
|
||||||
|
description: 'Description',
|
||||||
|
onClose: sinon.spy(),
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(<InfoBox {...props} />)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders title from props', () => {
|
||||||
|
const title = wrapper.find('.info-box__title')
|
||||||
|
assert.equal(title.text(), props.title)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders description from props', () => {
|
||||||
|
const description = wrapper.find('.info-box__description')
|
||||||
|
assert.equal(description.text(), props.description)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('closes info box', () => {
|
||||||
|
const close = wrapper.find('.info-box__close')
|
||||||
|
close.simulate('click')
|
||||||
|
assert(props.onClose.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
94
ui/app/components/app/menu-bar/tests/menu-bar.test.js
Normal file
94
ui/app/components/app/menu-bar/tests/menu-bar.test.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import configureStore from 'redux-mock-store'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mountWithRouter } from '../../../../../../test/lib/render-helpers'
|
||||||
|
import MenuBar from '../index'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
|
||||||
|
describe('MenuBar', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const mockStore = {
|
||||||
|
metamask: {
|
||||||
|
network: '1',
|
||||||
|
selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||||
|
identities: {
|
||||||
|
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': {
|
||||||
|
address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||||
|
name: 'Account 1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
keyrings: [
|
||||||
|
{
|
||||||
|
type: 'HD Key Tree',
|
||||||
|
accounts: [
|
||||||
|
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
frequentRpcListDetail: [],
|
||||||
|
},
|
||||||
|
appState: {
|
||||||
|
sidebar: {
|
||||||
|
isOpen: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = configureStore()(mockStore)
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
sinon.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows side bar when sidbarOpen is set to false', () => {
|
||||||
|
const props = {
|
||||||
|
showSidebar: sinon.spy(),
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper = mountWithRouter(
|
||||||
|
<Provider store={store}>
|
||||||
|
<MenuBar.WrappedComponent {...props} />
|
||||||
|
</Provider>, store
|
||||||
|
)
|
||||||
|
|
||||||
|
const sidebarButton = wrapper.find('.menu-bar__sidebar-button')
|
||||||
|
sidebarButton.simulate('click')
|
||||||
|
assert(props.showSidebar.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('hides side when sidebarOpen is set to true', () => {
|
||||||
|
const props = {
|
||||||
|
showSidebar: sinon.spy(),
|
||||||
|
hideSidebar: sinon.spy(),
|
||||||
|
sidebarOpen: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper = mountWithRouter(
|
||||||
|
<Provider store={store}>
|
||||||
|
<MenuBar.WrappedComponent {...props} />
|
||||||
|
</Provider>, store
|
||||||
|
)
|
||||||
|
|
||||||
|
const sidebarButton = wrapper.find('.menu-bar__sidebar-button')
|
||||||
|
sidebarButton.prop('onClick')()
|
||||||
|
assert(props.hideSidebar.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('opens account detail menu when account options is clicked', () => {
|
||||||
|
const accountOptions = wrapper.find('.menu-bar__open-in-browser')
|
||||||
|
accountOptions.simulate('click')
|
||||||
|
assert.equal(wrapper.find('MenuBar').instance().state.accountDetailsMenuOpen, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets accountDetailsMenuOpen to false when closed', () => {
|
||||||
|
wrapper.find('MenuBar').instance().setState({ accountDetailsMenuOpen: true })
|
||||||
|
wrapper.update()
|
||||||
|
|
||||||
|
const accountDetailsMenu = wrapper.find('AccountDetailsDropdown')
|
||||||
|
accountDetailsMenu.prop('onClose')()
|
||||||
|
|
||||||
|
assert.equal(wrapper.find('MenuBar').instance().state.accountDetailsMenuOpen, false)
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,58 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import ConfirmDeleteNetwork from '../index'
|
||||||
|
|
||||||
|
describe('Confirm Delete Network', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
hideModal: sinon.spy(),
|
||||||
|
delRpcTarget: sinon.stub().resolves(),
|
||||||
|
onConfirm: sinon.spy(),
|
||||||
|
target: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<ConfirmDeleteNetwork.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.hideModal.resetHistory()
|
||||||
|
props.delRpcTarget.resetHistory()
|
||||||
|
props.onConfirm.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders delete network modal title', () => {
|
||||||
|
const modalTitle = wrapper.find('.modal-content__title')
|
||||||
|
assert.equal(modalTitle.text(), 'deleteNetwork')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks cancel to hide modal', () => {
|
||||||
|
const cancelButton = wrapper.find('.button.btn-default.modal-container__footer-button')
|
||||||
|
cancelButton.simulate('click')
|
||||||
|
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks delete to delete the target and hides modal', () => {
|
||||||
|
const deleteButton = wrapper.find('.button.btn-danger.modal-container__footer-button')
|
||||||
|
|
||||||
|
deleteButton.simulate('click')
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
assert(props.delRpcTarget.calledOnce)
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
assert(props.onConfirm.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
@ -0,0 +1,82 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import configureStore from 'redux-mock-store'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import ConfirmRemoveAccount from '../index'
|
||||||
|
|
||||||
|
describe('Confirm Remove Account', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
hideModal: sinon.spy(),
|
||||||
|
removeAccount: sinon.stub().resolves(),
|
||||||
|
network: '101',
|
||||||
|
identity: {
|
||||||
|
address: '0xAddress',
|
||||||
|
name: 'Account 1',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const mockStore = configureStore()
|
||||||
|
const store = mockStore(state)
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider store={store} >
|
||||||
|
<ConfirmRemoveAccount.WrappedComponent {...props} />
|
||||||
|
</Provider>, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
store,
|
||||||
|
},
|
||||||
|
childContextTypes: {
|
||||||
|
t: PropTypes.func,
|
||||||
|
store: PropTypes.object,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.hideModal.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nevermind', () => {
|
||||||
|
const nevermind = wrapper.find({ type: 'default' })
|
||||||
|
nevermind.simulate('click')
|
||||||
|
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('remove', (done) => {
|
||||||
|
const remove = wrapper.find({ type: 'secondary' })
|
||||||
|
remove.simulate('click')
|
||||||
|
|
||||||
|
assert(props.removeAccount.calledOnce)
|
||||||
|
assert.equal(props.removeAccount.getCall(0).args[0], props.identity.address)
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('closes', () => {
|
||||||
|
const close = wrapper.find('.modal-container__header-close')
|
||||||
|
close.simulate('click')
|
||||||
|
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,46 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import ConfirmResetAccount from '../index'
|
||||||
|
|
||||||
|
describe('Confirm Reset Account', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
hideModal: sinon.spy(),
|
||||||
|
resetAccount: sinon.stub().resolves(),
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<ConfirmResetAccount.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.hideModal.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('hides modal when nevermind button is clicked', () => {
|
||||||
|
const nevermind = wrapper.find('.btn-default.modal-container__footer-button')
|
||||||
|
nevermind.simulate('click')
|
||||||
|
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('resets account and hidels modal when reset button is clicked', (done) => {
|
||||||
|
const reset = wrapper.find('.btn-danger.modal-container__footer-button')
|
||||||
|
reset.simulate('click')
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
assert(props.resetAccount.calledOnce)
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,55 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import MetaMetricsOptIn from '../index'
|
||||||
|
|
||||||
|
describe('MetaMetrics Opt In', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
setParticipateInMetaMetrics: sinon.stub().resolves(),
|
||||||
|
hideModal: sinon.spy(),
|
||||||
|
participateInMetaMetrics: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<MetaMetricsOptIn.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
metricsEvent: () => {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.setParticipateInMetaMetrics.resetHistory()
|
||||||
|
props.hideModal.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('passes false to setParticipateInMetaMetrics and hides modal', (done) => {
|
||||||
|
const noThanks = wrapper.find('.btn-default.page-container__footer-button')
|
||||||
|
noThanks.simulate('click')
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
assert(props.setParticipateInMetaMetrics.calledOnce)
|
||||||
|
assert.equal(props.setParticipateInMetaMetrics.getCall(0).args[0], false)
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('passes true to setParticipateInMetaMetrics and hides modal', (done) => {
|
||||||
|
const iAgree = wrapper.find('.btn-primary.page-container__footer-button')
|
||||||
|
iAgree.simulate('click')
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
assert(props.setParticipateInMetaMetrics.calledOnce)
|
||||||
|
assert.equal(props.setParticipateInMetaMetrics.getCall(0).args[0], true)
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import RejectTransactionsModal from '../index'
|
||||||
|
|
||||||
|
describe('Reject Transactions Model', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
onSubmit: sinon.spy(),
|
||||||
|
hideModal: sinon.spy(),
|
||||||
|
unapprovedTxCount: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<RejectTransactionsModal.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.hideModal.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('hides modal when cancel button is clicked', () => {
|
||||||
|
const cancelButton = wrapper.find('.btn-default.modal-container__footer-button')
|
||||||
|
cancelButton.simulate('click')
|
||||||
|
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('onSubmit is called and hides modal when reject all clicked', (done) => {
|
||||||
|
const rejectAllButton = wrapper.find('.btn-secondary.modal-container__footer-button')
|
||||||
|
rejectAllButton.simulate('click')
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
assert(props.onSubmit.calledOnce)
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,82 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import AccountDetailsModal from '../account-details-modal'
|
||||||
|
|
||||||
|
describe('Account Details Modal', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
global.platform = { openWindow: sinon.spy() }
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
hideModal: sinon.spy(),
|
||||||
|
setAccountLabel: sinon.spy(),
|
||||||
|
showExportPrivateKeyModal: sinon.spy(),
|
||||||
|
showQrView: sinon.spy(),
|
||||||
|
network: 'test',
|
||||||
|
rpcPrefs: {},
|
||||||
|
selectedIdentity: {
|
||||||
|
address: '0xAddress',
|
||||||
|
name: 'Account 1',
|
||||||
|
},
|
||||||
|
keyrings: [
|
||||||
|
{
|
||||||
|
type: 'HD Key Tree',
|
||||||
|
accounts: [
|
||||||
|
'0xAddress',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
identities: {
|
||||||
|
'0xAddress': {
|
||||||
|
address: '0xAddress',
|
||||||
|
name: 'Account 1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(
|
||||||
|
<AccountDetailsModal.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets account label when changing default account label', () => {
|
||||||
|
const accountLabel = wrapper.find('.account-modal__name').first()
|
||||||
|
accountLabel.simulate('submit', 'New Label')
|
||||||
|
|
||||||
|
assert(props.setAccountLabel.calledOnce)
|
||||||
|
assert.equal(props.setAccountLabel.getCall(0).args[1], 'New Label')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('opens new window when view block explorer is clicked', () => {
|
||||||
|
const modalButton = wrapper.find('.account-modal__button')
|
||||||
|
const etherscanLink = modalButton.first()
|
||||||
|
|
||||||
|
etherscanLink.simulate('click')
|
||||||
|
assert(global.platform.openWindow.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows export private key modal when clicked', () => {
|
||||||
|
const modalButton = wrapper.find('.account-modal__button')
|
||||||
|
const etherscanLink = modalButton.last()
|
||||||
|
|
||||||
|
etherscanLink.simulate('click')
|
||||||
|
assert(props.showExportPrivateKeyModal.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets blockexplorerview text when block explorer url in rpcPrefs exists', () => {
|
||||||
|
const blockExplorerUrl = 'https://block.explorer'
|
||||||
|
wrapper.setProps({ rpcPrefs: { blockExplorerUrl } })
|
||||||
|
|
||||||
|
const modalButton = wrapper.find('.account-modal__button')
|
||||||
|
const blockExplorerLink = modalButton.first()
|
||||||
|
|
||||||
|
assert.equal(blockExplorerLink.html(), '<button class="button btn-secondary account-modal__button">blockExplorerView</button>')
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import TransactionConfirmed from '../index'
|
||||||
|
|
||||||
|
describe('Transaction Confirmed', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
onSubmit: sinon.spy(),
|
||||||
|
hideModal: sinon.spy(),
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<TransactionConfirmed.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks ok to submit and hide modal', () => {
|
||||||
|
const submit = wrapper.find('.btn-secondary.modal-container__footer-button')
|
||||||
|
submit.simulate('click')
|
||||||
|
|
||||||
|
assert(props.onSubmit.calledOnce)
|
||||||
|
assert(props.hideModal.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
69
ui/app/components/app/tests/signature-request.test.js
Normal file
69
ui/app/components/app/tests/signature-request.test.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import configureMockStore from 'redux-mock-store'
|
||||||
|
import { mountWithRouter } from '../../../../../test/lib/render-helpers'
|
||||||
|
import SignatureRequest from '../signature-request'
|
||||||
|
|
||||||
|
describe('Signature Request', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const mockStore = {
|
||||||
|
metamask: {
|
||||||
|
provider: {
|
||||||
|
type: 'test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const store = configureMockStore()(mockStore)
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
selectedAccount: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5',
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
clearConfirmTransaction: sinon.spy(),
|
||||||
|
cancelMessage: sinon.spy(),
|
||||||
|
cancel: sinon.stub().resolves(),
|
||||||
|
sign: sinon.stub().resolves(),
|
||||||
|
txData: {
|
||||||
|
msgParams: {
|
||||||
|
id: 1,
|
||||||
|
data: '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Person":[{"name":"name","type":"string"},{"name":"wallet","type":"address"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person"},{"name":"contents","type":"string"}]},"primaryType":"Mail","domain":{"name":"Ether Mail","version":"1","chainId":"4","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"},"message":{"from":{"name":"Cow","wallet":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"},"to":{"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"},"contents":"Hello, Bob!"}}',
|
||||||
|
from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5',
|
||||||
|
origin: 'test.domain',
|
||||||
|
},
|
||||||
|
status: 'unapproved',
|
||||||
|
time: 1,
|
||||||
|
type: 'eth_sign',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mountWithRouter(
|
||||||
|
<Provider store={store}>
|
||||||
|
<SignatureRequest.WrappedComponent {...props} />
|
||||||
|
</Provider>, store
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.clearConfirmTransaction.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('cancel', () => {
|
||||||
|
const cancelButton = wrapper.find('button.btn-default')
|
||||||
|
cancelButton.simulate('click')
|
||||||
|
|
||||||
|
assert(props.cancel.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sign', () => {
|
||||||
|
const signButton = wrapper.find('button.btn-primary')
|
||||||
|
signButton.simulate('click')
|
||||||
|
|
||||||
|
assert(props.sign.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
69
ui/app/components/app/tests/token-cell.spec.js
Normal file
69
ui/app/components/app/tests/token-cell.spec.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import thunk from 'redux-thunk'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import configureMockStore from 'redux-mock-store'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
|
||||||
|
import TokenCell from '../token-cell'
|
||||||
|
import Identicon from '../../ui/identicon'
|
||||||
|
|
||||||
|
describe('Token Cell', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
network: 'test',
|
||||||
|
currentCurrency: 'usd',
|
||||||
|
selectedTokenAddress: '0xToken',
|
||||||
|
selectedAddress: '0xAddress',
|
||||||
|
contractExchangeRates: {
|
||||||
|
'0xAnotherToken': 0.015,
|
||||||
|
},
|
||||||
|
conversionRate: 7.00,
|
||||||
|
},
|
||||||
|
appState: {
|
||||||
|
sidebar: {
|
||||||
|
isOpen: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const middlewares = [thunk]
|
||||||
|
const mockStore = configureMockStore(middlewares)
|
||||||
|
const store = mockStore(state)
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<Provider store={store}>
|
||||||
|
<TokenCell
|
||||||
|
address="0xAnotherToken"
|
||||||
|
symbol="TEST"
|
||||||
|
string="5.000"
|
||||||
|
network={22}
|
||||||
|
currentCurrency="usd"
|
||||||
|
image="./test-image"
|
||||||
|
/>
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders Identicon with props from token cell', () => {
|
||||||
|
assert.equal(wrapper.find(Identicon).prop('address'), '0xAnotherToken')
|
||||||
|
assert.equal(wrapper.find(Identicon).prop('network'), 'test')
|
||||||
|
assert.equal(wrapper.find(Identicon).prop('image'), './test-image')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders token balance', () => {
|
||||||
|
assert.equal(wrapper.find('.token-list-item__token-balance').text(), '5.000')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders token symbol', () => {
|
||||||
|
assert.equal(wrapper.find('.token-list-item__token-symbol').text(), 'TEST')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders converted fiat amount', () => {
|
||||||
|
assert.equal(wrapper.find('.token-list-item__fiat-amount').text(), '0.52 USD')
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
43
ui/app/components/ui/alert/tests/alert.test.js
Normal file
43
ui/app/components/ui/alert/tests/alert.test.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import Alert from '../index'
|
||||||
|
|
||||||
|
describe('Alert', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallow(
|
||||||
|
<Alert />
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders nothing with no visible boolean in state', () => {
|
||||||
|
const alert = wrapper.find('.global-alert')
|
||||||
|
assert.equal(alert.length, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders when visible in state is true, and message', () => {
|
||||||
|
const errorMessage = 'Error Message'
|
||||||
|
|
||||||
|
wrapper.setState({ visible: true, msg: errorMessage })
|
||||||
|
|
||||||
|
const alert = wrapper.find('.global-alert')
|
||||||
|
assert.equal(alert.length, 1)
|
||||||
|
|
||||||
|
const errorText = wrapper.find('.msg')
|
||||||
|
assert.equal(errorText.text(), errorMessage)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls component method when componentWillReceiveProps is called', () => {
|
||||||
|
const animateInSpy = sinon.stub(wrapper.instance(), 'animateIn')
|
||||||
|
const animateOutSpy = sinon.stub(wrapper.instance(), 'animateOut')
|
||||||
|
|
||||||
|
wrapper.setProps({ visible: true })
|
||||||
|
assert(animateInSpy.calledOnce)
|
||||||
|
|
||||||
|
wrapper.setProps({ visible: false })
|
||||||
|
assert(animateOutSpy.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,44 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import withTokenTracker from '../with-token-tracker.component'
|
||||||
|
import TokenBalance from '../../../../components/ui/token-balance/token-balance.component'
|
||||||
|
// import sinon from 'sinon'
|
||||||
|
import TokenTracker from 'eth-token-tracker'
|
||||||
|
|
||||||
|
const { createTestProviderTools } = require('../../../../../../test/stub/provider')
|
||||||
|
|
||||||
|
const provider = createTestProviderTools({ scaffold: {} }).provider
|
||||||
|
|
||||||
|
describe('WithTokenTracker HOC', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const TokenTracker = withTokenTracker(TokenBalance)
|
||||||
|
wrapper = shallow(
|
||||||
|
<TokenTracker
|
||||||
|
userAddress="0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"
|
||||||
|
token={
|
||||||
|
{
|
||||||
|
address: 'test',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('#setError', () => {
|
||||||
|
wrapper.instance().setError('test')
|
||||||
|
assert.equal(wrapper.props().error, 'test')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('#updateBalance', () => {
|
||||||
|
wrapper.instance().tracker = new TokenTracker({
|
||||||
|
provider,
|
||||||
|
})
|
||||||
|
wrapper.instance().updateBalance([{ string: 'test string', symbol: 'test symbol' }])
|
||||||
|
assert.equal(wrapper.props().string, 'test string')
|
||||||
|
assert.equal(wrapper.props().symbol, 'test symbol')
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
100
ui/app/pages/add-token/tests/add-token.test.js
Normal file
100
ui/app/pages/add-token/tests/add-token.test.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import configureMockStore from 'redux-mock-store'
|
||||||
|
import { mountWithRouter } from '../../../../../test/lib/render-helpers'
|
||||||
|
import AddToken from '../index'
|
||||||
|
|
||||||
|
describe('Add Token', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
tokens: [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockStore = configureMockStore()
|
||||||
|
const store = mockStore(state)
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
history: {
|
||||||
|
push: sinon.stub().callsFake(() => {}),
|
||||||
|
},
|
||||||
|
setPendingTokens: sinon.spy(),
|
||||||
|
clearPendingTokens: sinon.spy(),
|
||||||
|
tokens: [],
|
||||||
|
identities: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
wrapper = mountWithRouter(
|
||||||
|
<Provider store={store}>
|
||||||
|
<AddToken.WrappedComponent {...props} />
|
||||||
|
</Provider>, store
|
||||||
|
)
|
||||||
|
|
||||||
|
wrapper.find({ name: 'customToken' }).simulate('click')
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.history.push.reset()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Add Token', () => {
|
||||||
|
|
||||||
|
it('next button is disabled when no fields are populated', () => {
|
||||||
|
const nextButton = wrapper.find('.button.btn-secondary.page-container__footer-button')
|
||||||
|
|
||||||
|
assert.equal(nextButton.props().disabled, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('edits token address', () => {
|
||||||
|
const tokenAddress = '0x617b3f8050a0BD94b6b1da02B4384eE5B4DF13F4'
|
||||||
|
const event = { target: { value: tokenAddress } }
|
||||||
|
const customAddress = wrapper.find('input#custom-address')
|
||||||
|
|
||||||
|
customAddress.simulate('change', event)
|
||||||
|
assert.equal(wrapper.find('AddToken').instance().state.customAddress, tokenAddress)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
it('edits token symbol', () => {
|
||||||
|
const tokenSymbol = 'META'
|
||||||
|
const event = { target: { value: tokenSymbol } }
|
||||||
|
const customAddress = wrapper.find('#custom-symbol')
|
||||||
|
customAddress.last().simulate('change', event)
|
||||||
|
|
||||||
|
assert.equal(wrapper.find('AddToken').instance().state.customSymbol, tokenSymbol)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('edits token decimal precision', () => {
|
||||||
|
const tokenPrecision = '2'
|
||||||
|
const event = { target: { value: tokenPrecision } }
|
||||||
|
const customAddress = wrapper.find('#custom-decimals')
|
||||||
|
customAddress.last().simulate('change', event)
|
||||||
|
|
||||||
|
assert.equal(wrapper.find('AddToken').instance().state.customDecimals, tokenPrecision)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('next', () => {
|
||||||
|
const nextButton = wrapper.find('.button.btn-secondary.page-container__footer-button')
|
||||||
|
nextButton.simulate('click')
|
||||||
|
|
||||||
|
assert(props.setPendingTokens.calledOnce)
|
||||||
|
assert(props.history.push.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/confirm-add-token')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('cancels', () => {
|
||||||
|
const cancelButton = wrapper.find('button.btn-default.page-container__footer-button')
|
||||||
|
cancelButton.simulate('click')
|
||||||
|
|
||||||
|
assert(props.clearPendingTokens.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
46
ui/app/pages/create-account/tests/create-account.test.js
Normal file
46
ui/app/pages/create-account/tests/create-account.test.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mountWithRouter } from '../../../../../test/lib/render-helpers'
|
||||||
|
import CreateAccountPage from '../index'
|
||||||
|
|
||||||
|
describe('Create Account Page', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
pathname: '/new-account',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
wrapper = mountWithRouter(
|
||||||
|
<CreateAccountPage {...props} />
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.history.push.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks create account and routes to new-account path', () => {
|
||||||
|
const createAccount = wrapper.find('.new-account__tabs__tab').at(0)
|
||||||
|
createAccount.simulate('click')
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/new-account')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks import account and routes to import new account path', () => {
|
||||||
|
const importAccount = wrapper.find('.new-account__tabs__tab').at(1)
|
||||||
|
importAccount.simulate('click')
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/new-account/import')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks connect HD Wallet and routes to connect new account path', () => {
|
||||||
|
const connectHdWallet = wrapper.find('.new-account__tabs__tab').at(2)
|
||||||
|
connectHdWallet.simulate('click')
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/new-account/connect')
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,39 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mountWithRouter } from '../../../../../../test/lib/render-helpers'
|
||||||
|
import { DEFAULT_ROUTE } from '../../../../helpers/constants/routes'
|
||||||
|
import EndOfFlowScreen from '../index'
|
||||||
|
|
||||||
|
describe('End of Flow Screen', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
completeOnboarding: sinon.spy(),
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mountWithRouter(
|
||||||
|
<EndOfFlowScreen.WrappedComponent {...props} />
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders', () => {
|
||||||
|
assert.equal(wrapper.length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('', (done) => {
|
||||||
|
const endOfFlowButton = wrapper.find('.btn-primary.first-time-flow__button')
|
||||||
|
endOfFlowButton.simulate('click')
|
||||||
|
|
||||||
|
setImmediate(() => {
|
||||||
|
assert(props.completeOnboarding.calledOnce)
|
||||||
|
assert(props.history.push.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], DEFAULT_ROUTE)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,73 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import { mountWithRouter } from '../../../../../../test/lib/render-helpers'
|
||||||
|
import {
|
||||||
|
DEFAULT_ROUTE,
|
||||||
|
LOCK_ROUTE,
|
||||||
|
INITIALIZE_WELCOME_ROUTE,
|
||||||
|
INITIALIZE_UNLOCK_ROUTE,
|
||||||
|
} from '../../../../helpers/constants/routes'
|
||||||
|
import FirstTimeFlowSwitch from '../index'
|
||||||
|
|
||||||
|
describe('FirstTimeFlowSwitch', () => {
|
||||||
|
|
||||||
|
it('redirects to /welcome route with no props', () => {
|
||||||
|
const wrapper = mountWithRouter(
|
||||||
|
<FirstTimeFlowSwitch.WrappedComponent />
|
||||||
|
)
|
||||||
|
assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: INITIALIZE_WELCOME_ROUTE } }).length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('redirects to / route when completedOnboarding is true', () => {
|
||||||
|
const props = {
|
||||||
|
completedOnboarding: true,
|
||||||
|
}
|
||||||
|
const wrapper = mountWithRouter(
|
||||||
|
<FirstTimeFlowSwitch.WrappedComponent {...props} />
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: DEFAULT_ROUTE } }).length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('redirects to /lock route when isUnlocked is true ', () => {
|
||||||
|
const props = {
|
||||||
|
completedOnboarding: false,
|
||||||
|
isUnlocked: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = mountWithRouter(
|
||||||
|
<FirstTimeFlowSwitch.WrappedComponent {...props} />
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: LOCK_ROUTE } }).length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('redirects to /welcome route when isInitialized is false', () => {
|
||||||
|
const props = {
|
||||||
|
completedOnboarding: false,
|
||||||
|
isUnlocked: false,
|
||||||
|
isInitialized: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = mountWithRouter(
|
||||||
|
<FirstTimeFlowSwitch.WrappedComponent {...props} />
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: INITIALIZE_WELCOME_ROUTE } }).length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('redirects to /unlock route when isInitialized is true', () => {
|
||||||
|
const props = {
|
||||||
|
completedOnboarding: false,
|
||||||
|
isUnlocked: false,
|
||||||
|
isInitialized: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = mountWithRouter(
|
||||||
|
<FirstTimeFlowSwitch.WrappedComponent {...props} />
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(wrapper.find('Lifecycle').find({ to: { pathname: INITIALIZE_UNLOCK_ROUTE } }).length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import configureMockStore from 'redux-mock-store'
|
||||||
|
import { mountWithRouter } from '../../../../../../test/lib/render-helpers'
|
||||||
|
import MetaMetricsOptIn from '../index'
|
||||||
|
|
||||||
|
describe('MetaMetricsOptIn', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
setParticipateInMetaMetrics: sinon.stub().resolves(),
|
||||||
|
participateInMetaMetrics: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockStore = {
|
||||||
|
metamask: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = configureMockStore()(mockStore)
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mountWithRouter(
|
||||||
|
<MetaMetricsOptIn.WrappedComponent {...props} />, store
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.setParticipateInMetaMetrics.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('opt out of metametrics', () => {
|
||||||
|
const noThanksButton = wrapper.find('.btn-default.page-container__footer-button')
|
||||||
|
noThanksButton.simulate('click')
|
||||||
|
|
||||||
|
assert(props.setParticipateInMetaMetrics.calledOnce)
|
||||||
|
assert.equal(props.setParticipateInMetaMetrics.getCall(0).args[0], false)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import RevealSeedPhrase from '../index'
|
||||||
|
|
||||||
|
describe('Reveal Seed Phrase', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
seedPhrase: TEST_SEED,
|
||||||
|
setSeedPhraseBackedUp: sinon.spy(),
|
||||||
|
setCompletedOnboarding: sinon.spy(),
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<RevealSeedPhrase.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
metricsEvent: () => {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('seed phrase', () => {
|
||||||
|
const seedPhrase = wrapper.find('.reveal-seed-phrase__secret-words--hidden')
|
||||||
|
assert.equal(seedPhrase.length, 1)
|
||||||
|
assert.equal(seedPhrase.text(), TEST_SEED)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks to reveal', () => {
|
||||||
|
const reveal = wrapper.find('.reveal-seed-phrase__secret-blocker')
|
||||||
|
|
||||||
|
assert.equal(wrapper.state().isShowingSeedPhrase, false)
|
||||||
|
reveal.simulate('click')
|
||||||
|
assert.equal(wrapper.state().isShowingSeedPhrase, true)
|
||||||
|
|
||||||
|
const showSeed = wrapper.find('.reveal-seed-phrase__secret-words')
|
||||||
|
assert.equal(showSeed.length, 1)
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,46 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mountWithRouter } from '../../../../../../test/lib/render-helpers'
|
||||||
|
import SelectAction from '../index'
|
||||||
|
|
||||||
|
describe('Selection Action', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
isInitialized: false,
|
||||||
|
setFirstTimeFlowType: sinon.spy(),
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mountWithRouter(
|
||||||
|
<SelectAction.WrappedComponent {...props} />
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
props.setFirstTimeFlowType.resetHistory()
|
||||||
|
props.history.push.resetHistory()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks import wallet to route to import FTF', () => {
|
||||||
|
const importWalletButton = wrapper.find('.btn-primary.first-time-flow__button').at(0)
|
||||||
|
importWalletButton.simulate('click')
|
||||||
|
|
||||||
|
assert(props.setFirstTimeFlowType.calledOnce)
|
||||||
|
assert.equal(props.setFirstTimeFlowType.getCall(0).args[0], 'import')
|
||||||
|
assert(props.history.push.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks create wallet to route to create FTF ', () => {
|
||||||
|
const createWalletButton = wrapper.find('.btn-primary.first-time-flow__button').at(1)
|
||||||
|
createWalletButton.simulate('click')
|
||||||
|
|
||||||
|
assert(props.setFirstTimeFlowType.calledOnce)
|
||||||
|
assert.equal(props.setFirstTimeFlowType.getCall(0).args[0], 'create')
|
||||||
|
assert(props.history.push.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
55
ui/app/pages/first-time-flow/welcome/tests/welcome.test.js
Normal file
55
ui/app/pages/first-time-flow/welcome/tests/welcome.test.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import configureMockStore from 'redux-mock-store'
|
||||||
|
import { mountWithRouter } from '../../../../../../test/lib/render-helpers'
|
||||||
|
import Welcome from '../index'
|
||||||
|
|
||||||
|
describe('Welcome', () => {
|
||||||
|
const mockStore = {
|
||||||
|
metamask: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = configureMockStore()(mockStore)
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
sinon.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('routes to select action when participateInMetaMetrics is not initialized', () => {
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = mountWithRouter(
|
||||||
|
<Welcome.WrappedComponent {...props} />, store
|
||||||
|
)
|
||||||
|
|
||||||
|
const getStartedButton = wrapper.find('.btn-primary.first-time-flow__button')
|
||||||
|
getStartedButton.simulate('click')
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/initialize/select-action')
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('routes to correct password when participateInMetaMetrics is initialized', () => {
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
welcomeScreenSeen: true,
|
||||||
|
participateInMetaMetrics: false,
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = mountWithRouter(
|
||||||
|
<Welcome.WrappedComponent {...props} />, store
|
||||||
|
)
|
||||||
|
|
||||||
|
const getStartedButton = wrapper.find('.btn-primary.first-time-flow__button')
|
||||||
|
getStartedButton.simulate('click')
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/initialize/create-password')
|
||||||
|
})
|
||||||
|
})
|
31
ui/app/pages/keychains/tests/reveal-seed.test.js
Normal file
31
ui/app/pages/keychains/tests/reveal-seed.test.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import RevealSeedPage from '../reveal-seed'
|
||||||
|
|
||||||
|
describe('Reveal Seed Page', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
requestRevealSeedWords: sinon.stub().resolves(),
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<RevealSeedPage.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('form submit', () => {
|
||||||
|
wrapper.find('form').simulate('submit')
|
||||||
|
assert(props.requestRevealSeedWords.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
48
ui/app/pages/lock/tests/lock.test.js
Normal file
48
ui/app/pages/lock/tests/lock.test.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mountWithRouter } from '../../../../../test/lib/render-helpers'
|
||||||
|
import Lock from '../index'
|
||||||
|
|
||||||
|
describe('Lock', () => {
|
||||||
|
|
||||||
|
it('replaces history with default route when isUnlocked false', () => {
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
isUnlocked: false,
|
||||||
|
history: {
|
||||||
|
replace: sinon.spy(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
mountWithRouter(
|
||||||
|
<Lock.WrappedComponent {...props} />
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(props.history.replace.getCall(0).args[0], '/')
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('locks and pushes history with default route when isUnlocked true', (done) => {
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
isUnlocked: true,
|
||||||
|
lockMetamask: sinon.stub(),
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
props.lockMetamask.resolves()
|
||||||
|
|
||||||
|
mountWithRouter(
|
||||||
|
<Lock.WrappedComponent {...props} />
|
||||||
|
)
|
||||||
|
|
||||||
|
assert(props.lockMetamask.calledOnce)
|
||||||
|
setImmediate(() => {
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,55 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import SecurityTab from '../index'
|
||||||
|
|
||||||
|
describe('Security Tab', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
revealSeedConfirmation: sinon.spy(),
|
||||||
|
showClearApprovalModal: sinon.spy(),
|
||||||
|
setParticipateInMetaMetrics: sinon.spy(),
|
||||||
|
displayWarning: sinon.spy(),
|
||||||
|
setShowIncomingTransactionsFeatureFlag: sinon.spy(),
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
privacyMode: true,
|
||||||
|
warning: '',
|
||||||
|
participateInMetaMetrics: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<SecurityTab.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
metricsEvent: () => {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('navigates to reveal seed words page', () => {
|
||||||
|
const seedWords = wrapper.find('.button.btn-danger.btn--large')
|
||||||
|
|
||||||
|
seedWords.simulate('click')
|
||||||
|
assert(props.history.push.calledOnce)
|
||||||
|
assert.equal(props.history.push.getCall(0).args[0], '/seed')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toggles incoming txs', () => {
|
||||||
|
const incomingTxs = wrapper.find({ type: 'checkbox' }).at(0)
|
||||||
|
incomingTxs.simulate('click')
|
||||||
|
assert(props.setShowIncomingTransactionsFeatureFlag.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toggles metaMetrics', () => {
|
||||||
|
const metaMetrics = wrapper.find({ type: 'checkbox' }).at(1)
|
||||||
|
|
||||||
|
metaMetrics.simulate('click')
|
||||||
|
assert(props.setParticipateInMetaMetrics.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,61 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import SettingsTab from '../index'
|
||||||
|
|
||||||
|
describe('Settings Tab', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
setCurrentCurrency: sinon.spy(),
|
||||||
|
displayWarning: sinon.spy(),
|
||||||
|
setUseBlockie: sinon.spy(),
|
||||||
|
updateCurrentLocale: sinon.spy(),
|
||||||
|
setUseNativeCurrencyAsPrimaryCurrencyPreference: sinon.spy(),
|
||||||
|
warning: '',
|
||||||
|
currentLocale: 'en',
|
||||||
|
useBlockie: false,
|
||||||
|
currentCurrency: 'usd',
|
||||||
|
conversionDate: 1,
|
||||||
|
nativeCurrency: 'eth',
|
||||||
|
useNativeCurrencyAsPrimaryCurrency: true,
|
||||||
|
}
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<SettingsTab.WrappedComponent {...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('selects currency', async () => {
|
||||||
|
const selectCurrency = wrapper.find({ placeholder: 'selectCurrency' })
|
||||||
|
|
||||||
|
selectCurrency.props().onSelect('eur')
|
||||||
|
assert(props.setCurrentCurrency.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('selects locale', async () => {
|
||||||
|
const selectLocale = wrapper.find({ placeholder: 'selectLocale' })
|
||||||
|
|
||||||
|
await selectLocale.props().onSelect('ja')
|
||||||
|
assert(props.updateCurrentLocale.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets fiat primary currency', () => {
|
||||||
|
const selectFiat = wrapper.find('#fiat-primary-currency')
|
||||||
|
|
||||||
|
selectFiat.simulate('change')
|
||||||
|
assert(props.setUseNativeCurrencyAsPrimaryCurrencyPreference.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toggles blockies', () => {
|
||||||
|
const toggleBlockies = wrapper.find({ type: 'checkbox' })
|
||||||
|
|
||||||
|
toggleBlockies.simulate('click')
|
||||||
|
assert(props.setUseBlockie.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
69
ui/app/pages/unlock-page/tests/unlock-page.test.js
Normal file
69
ui/app/pages/unlock-page/tests/unlock-page.test.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import assert from 'assert'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
import { mount } from 'enzyme'
|
||||||
|
import UnlockPage from '../index'
|
||||||
|
|
||||||
|
describe('Unlock Page', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
history: {
|
||||||
|
push: sinon.spy(),
|
||||||
|
},
|
||||||
|
isUnlocked: false,
|
||||||
|
onImport: sinon.spy(),
|
||||||
|
onRestore: sinon.spy(),
|
||||||
|
onSubmit: sinon.spy(),
|
||||||
|
forceUpdateMetamaskState: sinon.spy(),
|
||||||
|
showOptInModal: sinon.spy(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
|
||||||
|
wrapper = mount(
|
||||||
|
<UnlockPage.WrappedComponent{...props} />, {
|
||||||
|
context: {
|
||||||
|
t: str => str,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
sinon.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders', () => {
|
||||||
|
assert.equal(wrapper.length, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('changes password and submits', () => {
|
||||||
|
const passwordField = wrapper.find({ type: 'password', id: 'password' })
|
||||||
|
const loginButton = wrapper.find({ type: 'submit' }).last()
|
||||||
|
|
||||||
|
const event = { target: { value: 'password' } }
|
||||||
|
assert.equal(wrapper.instance().state.password, '')
|
||||||
|
passwordField.last().simulate('change', event)
|
||||||
|
assert.equal(wrapper.instance().state.password, 'password')
|
||||||
|
|
||||||
|
loginButton.simulate('click')
|
||||||
|
assert(props.onSubmit.calledOnce)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks imports seed button', () => {
|
||||||
|
const importSeedButton = wrapper.find('.unlock-page__link--import')
|
||||||
|
|
||||||
|
importSeedButton.simulate('click')
|
||||||
|
assert(props.onImport.calledOnce)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicks restore', () => {
|
||||||
|
const restoreFromSeedButton = wrapper.find('.unlock-page__link').at(0)
|
||||||
|
restoreFromSeedButton.simulate('click')
|
||||||
|
assert(props.onRestore.calledOnce)
|
||||||
|
})
|
||||||
|
})
|
@ -94,6 +94,7 @@ export default class UnlockPage extends Component {
|
|||||||
this.setState({ password: target.value, error: null })
|
this.setState({ password: target.value, error: null })
|
||||||
|
|
||||||
// tell mascot to look at page action
|
// tell mascot to look at page action
|
||||||
|
if (target.getBoundingClientRect) {
|
||||||
const element = target
|
const element = target
|
||||||
const boundingRect = element.getBoundingClientRect()
|
const boundingRect = element.getBoundingClientRect()
|
||||||
const coordinates = getCaretCoordinates(element, element.selectionEnd)
|
const coordinates = getCaretCoordinates(element, element.selectionEnd)
|
||||||
@ -102,6 +103,7 @@ export default class UnlockPage extends Component {
|
|||||||
y: boundingRect.top + coordinates.top - element.scrollTop,
|
y: boundingRect.top + coordinates.top - element.scrollTop,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderSubmitButton () {
|
renderSubmitButton () {
|
||||||
const style = {
|
const style = {
|
||||||
|
159
ui/app/selectors/tests/confirm-transaction.test.js
Normal file
159
ui/app/selectors/tests/confirm-transaction.test.js
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import assert from 'assert'
|
||||||
|
import {
|
||||||
|
unconfirmedTransactionsCountSelector,
|
||||||
|
tokenAmountAndToAddressSelector,
|
||||||
|
approveTokenAmountAndToAddressSelector,
|
||||||
|
sendTokenTokenAmountAndToAddressSelector,
|
||||||
|
contractExchangeRateSelector,
|
||||||
|
} from '../confirm-transaction'
|
||||||
|
|
||||||
|
describe('Confirm Transaction Selector', () => {
|
||||||
|
|
||||||
|
describe('unconfirmedTransactionsCountSelector', () => {
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
unapprovedTxs: {
|
||||||
|
1: {
|
||||||
|
metamaskNetworkId: 'test',
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
metmaskNetworkId: 'other network',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
unapprovedMsgCount: 1,
|
||||||
|
unapprovedPersonalMsgCount: 1,
|
||||||
|
unapprovedTypedMessagesCount: 1,
|
||||||
|
network: 'test',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns number of txs in unapprovedTxs state with the same network plus unapproved signing method counts', () => {
|
||||||
|
assert.equal(unconfirmedTransactionsCountSelector(state), 4)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('tokenAmountAndToAddressSelector', () => {
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
confirmTransaction: {
|
||||||
|
tokenData: {
|
||||||
|
name: 'transfer',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: '_to',
|
||||||
|
value: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||||
|
type: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_value',
|
||||||
|
value: '1',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
tokenProps: {
|
||||||
|
tokenDecimals: '2',
|
||||||
|
tokenSymbol: 'META',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns calulcated token amount based on token value and token decimals and recipient address', () => {
|
||||||
|
assert.deepEqual(tokenAmountAndToAddressSelector(state),
|
||||||
|
{ toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: 0.01 })
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('approveTokenAmountAndToAddressSelector', () => {
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
confirmTransaction: {
|
||||||
|
tokenData: {
|
||||||
|
name: 'approve',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: '_spender',
|
||||||
|
value: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||||
|
type: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_value',
|
||||||
|
value: '1',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
tokenProps: {
|
||||||
|
tokenDecimals: '2',
|
||||||
|
tokenSymbol: 'META',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns token amount and recipient for approve token allocation spending', () => {
|
||||||
|
assert.deepEqual(approveTokenAmountAndToAddressSelector(state),
|
||||||
|
{ toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: 0.01 })
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('sendTokenTokenAmountAndToAddressSelector', () => {
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
confirmTransaction: {
|
||||||
|
tokenData: {
|
||||||
|
name: 'transfer',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: '_to',
|
||||||
|
value: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||||
|
type: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_value',
|
||||||
|
value: '1',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
tokenProps: {
|
||||||
|
tokenDecimals: '2',
|
||||||
|
tokenSymbol: 'META',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns token address and calculated token amount', () => {
|
||||||
|
assert.deepEqual(sendTokenTokenAmountAndToAddressSelector(state),
|
||||||
|
{ toAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', tokenAmount: 0.01 })
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('contractExchangeRateSelector', () => {
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
contractExchangeRates: {
|
||||||
|
'0xTokenAddress': '10',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
confirmTransaction: {
|
||||||
|
txData: {
|
||||||
|
txParams: {
|
||||||
|
to: '0xTokenAddress',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns contract exchange rate in metamask state based on confirm transaction txParams token recipient', () => {
|
||||||
|
assert.equal(contractExchangeRateSelector(state), 10)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
28
ui/app/selectors/tests/tokens.test.js
Normal file
28
ui/app/selectors/tests/tokens.test.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import assert from 'assert'
|
||||||
|
import { selectedTokenSelector } from '../tokens'
|
||||||
|
|
||||||
|
const metaToken = {
|
||||||
|
'address': '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4',
|
||||||
|
'symbol': 'META',
|
||||||
|
'decimals': 18,
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
selectedTokenAddress: '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4',
|
||||||
|
tokens: [
|
||||||
|
{
|
||||||
|
'address': '0x06012c8cf97bead5deae237070f9587f8e7a266d',
|
||||||
|
'symbol': 'CK',
|
||||||
|
'decimals': 0,
|
||||||
|
},
|
||||||
|
metaToken,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
describe('Selected Token Selector', () => {
|
||||||
|
it('selects token info from tokens based on selectedTokenAddress in state', () => {
|
||||||
|
const tokenInfo = selectedTokenSelector(state)
|
||||||
|
assert.equal(tokenInfo, metaToken)
|
||||||
|
})
|
||||||
|
})
|
356
ui/app/selectors/tests/transactions.test.js
Normal file
356
ui/app/selectors/tests/transactions.test.js
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
import assert from 'assert'
|
||||||
|
import {
|
||||||
|
unapprovedMessagesSelector,
|
||||||
|
transactionsSelector,
|
||||||
|
nonceSortedTransactionsSelector,
|
||||||
|
nonceSortedPendingTransactionsSelector,
|
||||||
|
nonceSortedCompletedTransactionsSelector,
|
||||||
|
submittedPendingTransactionsSelector,
|
||||||
|
} from '../transactions'
|
||||||
|
|
||||||
|
describe('Transaction Selectors', () => {
|
||||||
|
|
||||||
|
describe('unapprovedMessagesSelector', () => {
|
||||||
|
it('returns eth sign msg from unapprovedMsgs', () => {
|
||||||
|
|
||||||
|
const msg = {
|
||||||
|
id: 1,
|
||||||
|
msgParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
data: '0xData',
|
||||||
|
origin: 'origin',
|
||||||
|
},
|
||||||
|
time: 1,
|
||||||
|
status: 'unapproved',
|
||||||
|
type: 'eth_sign',
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
unapprovedMsgs: {
|
||||||
|
1: msg,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgSelector = unapprovedMessagesSelector(state)
|
||||||
|
|
||||||
|
assert(Array.isArray(msgSelector))
|
||||||
|
assert.deepEqual(msgSelector, [msg])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns personal sign from unapprovedPersonalMsgsSelector', () => {
|
||||||
|
|
||||||
|
const msg = {
|
||||||
|
id: 1,
|
||||||
|
msgParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
data: '0xData',
|
||||||
|
origin: 'origin',
|
||||||
|
},
|
||||||
|
time: 1,
|
||||||
|
status: 'unapproved',
|
||||||
|
type: 'personal_sign',
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
unapprovedPersonalMsgs: {
|
||||||
|
1: msg,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgSelector = unapprovedMessagesSelector(state)
|
||||||
|
|
||||||
|
assert(Array.isArray(msgSelector))
|
||||||
|
assert.deepEqual(msgSelector, [msg])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns typed message from unapprovedTypedMessagesSelector', () => {
|
||||||
|
|
||||||
|
const msg = {
|
||||||
|
id: 1,
|
||||||
|
msgParams: {
|
||||||
|
data: '0xData',
|
||||||
|
from: '0xAddress',
|
||||||
|
version: 'V3',
|
||||||
|
origin: 'origin',
|
||||||
|
},
|
||||||
|
time: 1,
|
||||||
|
status: 'unapproved',
|
||||||
|
type: 'eth_signTypedData',
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
unapprovedTypedMessages: {
|
||||||
|
1: msg,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgSelector = unapprovedMessagesSelector(state)
|
||||||
|
|
||||||
|
assert(Array.isArray(msgSelector))
|
||||||
|
assert.deepEqual(msgSelector, [msg])
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('transactionsSelector', () => {
|
||||||
|
|
||||||
|
it('selectedAddressTxList', () => {
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
featureFlags: {
|
||||||
|
showIncomingTransactions: false,
|
||||||
|
},
|
||||||
|
selectedAddressTxList: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
time: 0,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
time: 1,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderedTxlist = state.metamask.selectedAddressTxList.sort((a, b) => b.time - a.time)
|
||||||
|
|
||||||
|
const txSelector = transactionsSelector(state)
|
||||||
|
|
||||||
|
assert(Array.isArray(txSelector))
|
||||||
|
assert.deepEqual(txSelector, orderedTxlist)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns token tx from selectedAddressTxList when selectedTokenAddress is valid', () => {
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
featureFlags: {
|
||||||
|
showIncomingTransactions: false,
|
||||||
|
},
|
||||||
|
selectedTokenAddress: '0xToken',
|
||||||
|
selectedAddressTxList: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
time: 0,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xToken',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
time: 1,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xToken',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderedTxlist = state.metamask.selectedAddressTxList.sort((a, b) => b.time - a.time)
|
||||||
|
|
||||||
|
const txSelector = transactionsSelector(state)
|
||||||
|
|
||||||
|
assert(Array.isArray(txSelector))
|
||||||
|
assert.deepEqual(txSelector, orderedTxlist)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('nonceSortedTransactionsSelector', () => {
|
||||||
|
|
||||||
|
it('returns transaction group nonce sorted tx from from selectedTxList wit', () => {
|
||||||
|
|
||||||
|
const tx1 = {
|
||||||
|
id: 0,
|
||||||
|
time: 0,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
nonce: '0x0',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const tx2 = {
|
||||||
|
id: 1,
|
||||||
|
time: 1,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
nonce: '0x1',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
featureFlags: {
|
||||||
|
showIncomingTransactions: false,
|
||||||
|
},
|
||||||
|
selectedAddressTxList: [
|
||||||
|
tx1,
|
||||||
|
tx2,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const expectedResult = [
|
||||||
|
{
|
||||||
|
nonce: '0x0',
|
||||||
|
transactions: [ tx1 ],
|
||||||
|
initialTransaction: tx1,
|
||||||
|
primaryTransaction: tx1,
|
||||||
|
hasRetried: false,
|
||||||
|
hasCancelled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nonce: '0x1',
|
||||||
|
transactions: [ tx2 ],
|
||||||
|
initialTransaction: tx2,
|
||||||
|
primaryTransaction: tx2,
|
||||||
|
hasRetried: false,
|
||||||
|
hasCancelled: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
assert.deepEqual(nonceSortedTransactionsSelector(state), expectedResult)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Sorting Transactions Selectors', () => {
|
||||||
|
|
||||||
|
const submittedTx = {
|
||||||
|
id: 0,
|
||||||
|
time: 0,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
nonce: '0x0',
|
||||||
|
},
|
||||||
|
status: 'submitted',
|
||||||
|
}
|
||||||
|
|
||||||
|
const unapprovedTx = {
|
||||||
|
id: 1,
|
||||||
|
time: 1,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
nonce: '0x1',
|
||||||
|
},
|
||||||
|
status: 'unapproved',
|
||||||
|
}
|
||||||
|
|
||||||
|
const approvedTx = {
|
||||||
|
id: 2,
|
||||||
|
time: 2,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
nonce: '0x2',
|
||||||
|
},
|
||||||
|
status: 'approved',
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmedTx = {
|
||||||
|
id: 3,
|
||||||
|
time: 3,
|
||||||
|
txParams: {
|
||||||
|
from: '0xAddress',
|
||||||
|
to: '0xRecipient',
|
||||||
|
nonce: '0x3',
|
||||||
|
},
|
||||||
|
status: 'confirmed',
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
metamask: {
|
||||||
|
featureFlags: {
|
||||||
|
showIncomingTransactions: false,
|
||||||
|
},
|
||||||
|
selectedAddressTxList: [
|
||||||
|
submittedTx,
|
||||||
|
unapprovedTx,
|
||||||
|
approvedTx,
|
||||||
|
confirmedTx,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
it('nonceSortedPendingTransactionsSelector', () => {
|
||||||
|
|
||||||
|
const expectedResult = [
|
||||||
|
{
|
||||||
|
nonce: submittedTx.txParams.nonce,
|
||||||
|
transactions: [ submittedTx ],
|
||||||
|
initialTransaction: submittedTx,
|
||||||
|
primaryTransaction: submittedTx,
|
||||||
|
hasRetried: false,
|
||||||
|
hasCancelled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nonce: unapprovedTx.txParams.nonce,
|
||||||
|
transactions: [ unapprovedTx ],
|
||||||
|
initialTransaction: unapprovedTx,
|
||||||
|
primaryTransaction: unapprovedTx,
|
||||||
|
hasRetried: false,
|
||||||
|
hasCancelled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nonce: approvedTx.txParams.nonce,
|
||||||
|
transactions: [ approvedTx ],
|
||||||
|
initialTransaction: approvedTx,
|
||||||
|
primaryTransaction: approvedTx,
|
||||||
|
hasRetried: false,
|
||||||
|
hasCancelled: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
assert.deepEqual(nonceSortedPendingTransactionsSelector(state), expectedResult)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nonceSortedCompletedTransactionsSelector', () => {
|
||||||
|
|
||||||
|
const expectedResult = [
|
||||||
|
{
|
||||||
|
nonce: confirmedTx.txParams.nonce,
|
||||||
|
transactions: [ confirmedTx ],
|
||||||
|
initialTransaction: confirmedTx,
|
||||||
|
primaryTransaction: confirmedTx,
|
||||||
|
hasRetried: false,
|
||||||
|
hasCancelled: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
assert.deepEqual(nonceSortedCompletedTransactionsSelector(state), expectedResult)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('submittedPendingTransactionsSelector', () => {
|
||||||
|
|
||||||
|
const expectedResult = [ submittedTx ]
|
||||||
|
assert.deepEqual(submittedPendingTransactionsSelector(state), expectedResult)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user