Merge pull request #7222 from MetaMask/background-controller-tests

Background / Controller tests.
feature/default_network_editable
Thomas Huang 5 years ago committed by GitHub
commit 3acd1db0be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 55
      test/unit/app/controllers/balance-controller.spec.js
  2. 46
      test/unit/app/controllers/metamask-controller-test.js
  3. 116
      test/unit/app/typed-message-manager.spec.js
  4. 546
      test/unit/ui/app/actions.spec.js

@ -0,0 +1,55 @@
const assert = require('assert')
const ObservableStore = require('obs-store')
const PollingBlockTracker = require('eth-block-tracker')
const BalanceController = require('../../../../app/scripts/controllers/balance')
const AccountTracker = require('../../../../app/scripts/lib/account-tracker')
const TransactionController = require('../../../../app/scripts/controllers/transactions')
const { createTestProviderTools } = require('../../../stub/provider')
const provider = createTestProviderTools({ scaffold: {}}).provider
const TEST_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'
const accounts = {
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': {
balance: '0x5e942b06dc24c4d50',
address: TEST_ADDRESS,
},
}
describe('Balance Controller', () => {
let balanceController
it('errors when address, accountTracker, txController, or blockTracker', function () {
try {
balanceController = new BalanceController()
} catch (error) {
assert.equal(error.message, 'Cannot construct a balance checker without address, accountTracker, txController, and blockTracker.')
}
})
beforeEach(() => {
balanceController = new BalanceController({
address: TEST_ADDRESS,
accountTracker: new AccountTracker({
provider,
blockTracker: new PollingBlockTracker({ provider }),
}),
txController: new TransactionController({
provider,
networkStore: new ObservableStore(),
blockTracker: new PollingBlockTracker({ provider }),
}),
blockTracker: new PollingBlockTracker({ provider }),
})
balanceController.accountTracker.store.updateState({ accounts })
})
it('updates balance controller ethBalance from account tracker', async function () {
await balanceController.updateBalance()
const balanceControllerState = balanceController.store.getState()
assert.equal(balanceControllerState.ethBalance, '0x5e942b06dc24c4d50')
})
})

@ -2,6 +2,7 @@ const assert = require('assert')
const sinon = require('sinon')
const clone = require('clone')
const nock = require('nock')
const ethUtil = require('ethereumjs-util')
const createThoughStream = require('through2').obj
const blacklistJSON = require('eth-phishing-detect/src/config')
const firstTimeState = require('../../../unit/localhostState')
@ -103,6 +104,51 @@ describe('MetaMaskController', function () {
sandbox.restore()
})
describe('#getAccounts', function () {
beforeEach(async function () {
const password = 'a-fake-password'
await metamaskController.createNewVaultAndRestore(password, TEST_SEED)
})
it('returns first address when dapp calls web3.eth.getAccounts', function () {
metamaskController.networkController._baseProviderParams.getAccounts((err, res) => {
assert.ifError(err)
assert.equal(res.length, 1)
assert.equal(res[0], '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc')
})
})
})
describe('#importAccountWithStrategy', function () {
const importPrivkey = '4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553'
beforeEach(async function () {
const password = 'a-fake-password'
await metamaskController.createNewVaultAndRestore(password, TEST_SEED)
await metamaskController.importAccountWithStrategy('Private Key', [ importPrivkey ])
})
it('adds private key to keyrings in KeyringController', async function () {
const simpleKeyrings = metamaskController.keyringController.getKeyringsByType('Simple Key Pair')
const privKeyBuffer = simpleKeyrings[0].wallets[0]._privKey
const pubKeyBuffer = simpleKeyrings[0].wallets[0]._pubKey
const addressBuffer = ethUtil.pubToAddress(pubKeyBuffer)
const privKey = ethUtil.bufferToHex(privKeyBuffer)
const pubKey = ethUtil.bufferToHex(addressBuffer)
assert.equal(privKey, ethUtil.addHexPrefix(importPrivkey))
assert.equal(pubKey, '0xe18035bf8712672935fdb4e5e431b1a0183d2dfc')
})
it('adds private key to keyrings in KeyringController', async function () {
const keyringAccounts = await metamaskController.keyringController.getAccounts()
assert.equal(keyringAccounts[keyringAccounts.length - 1], '0xe18035bf8712672935fdb4e5e431b1a0183d2dfc')
})
})
describe('submitPassword', function () {
const password = 'password'

@ -0,0 +1,116 @@
import assert from 'assert'
import sinon from 'sinon'
import NetworkController from '../../../app/scripts/controllers/network/index'
import TypedMessageManager from '../../../app/scripts/lib/typed-message-manager'
describe('Typed Message Manager', () => {
let typedMessageManager, msgParamsV1, msgParamsV3, typedMsgs, messages, msgId, numberMsgId
const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'
const networkController = new NetworkController()
sinon.stub(networkController, 'getNetworkState').returns('1')
beforeEach(() => {
typedMessageManager = new TypedMessageManager({
networkController,
})
msgParamsV1 = {
from: address,
data: [
{ type: 'string', name: 'unit test', value: 'hello there' },
{ type: 'uint32', name: 'A number, but not really a number', value: '$$$' },
],
}
msgParamsV3 = {
from: address,
data: JSON.stringify({
'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 Mainl',
'version': '1',
'chainId': 1,
'verifyingContract': '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
},
'message': {
'from': {
'name': 'Cow',
'wallet': '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
},
'to': {
'name': 'Bob',
'wallet': '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
'contents': 'Hello, Bob!',
},
}),
}
typedMessageManager.addUnapprovedMessage(msgParamsV3, 'V3')
typedMsgs = typedMessageManager.getUnapprovedMsgs()
messages = typedMessageManager.messages
msgId = Object.keys(typedMsgs)[0]
messages[0].msgParams.metamaskId = parseInt(msgId)
numberMsgId = parseInt(msgId)
})
it('supports version 1 of signedTypedData', () => {
typedMessageManager.addUnapprovedMessage(msgParamsV1, 'V1')
assert.equal(messages[messages.length - 1].msgParams.data, msgParamsV1.data)
})
it('has params address', function () {
assert.equal(typedMsgs[msgId].msgParams.from, address)
})
it('adds to unapproved messages and sets status to unapproved', function () {
assert.equal(typedMsgs[msgId].status, 'unapproved')
})
it('validates params', function () {
assert.doesNotThrow(() => {
typedMessageManager.validateParams(messages[0])
}, 'Does not throw with valid parameters')
})
it('gets unapproved by id', function () {
const getMsg = typedMessageManager.getMsg(numberMsgId)
assert.equal(getMsg.id, numberMsgId)
})
it('approves messages', async function () {
const messageMetaMaskId = messages[0].msgParams
typedMessageManager.approveMessage(messageMetaMaskId)
assert.equal(messages[0].status, 'approved')
})
it('sets msg status to signed and adds a raw sig to message details', function () {
typedMessageManager.setMsgStatusSigned(numberMsgId, 'raw sig')
assert.equal(messages[0].status, 'signed')
assert.equal(messages[0].rawSig, 'raw sig')
})
it('rejects message', function () {
typedMessageManager.rejectMsg(numberMsgId)
assert.equal(messages[0].status, 'rejected')
})
})

@ -1,3 +1,4 @@
/* eslint-disable */
// Used to inspect long objects
// util.inspect({JSON}, false, null))
// const util = require('util')
@ -29,6 +30,8 @@ describe('Actions', () => {
const noop = () => {}
const currentNetworkId = 42
let background, metamaskController
const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'
@ -37,7 +40,6 @@ describe('Actions', () => {
beforeEach(async () => {
metamaskController = new MetaMaskController({
provider,
keyringController: new KeyringController({}),
@ -88,11 +90,9 @@ describe('Actions', () => {
submitPasswordSpy = sinon.spy(background, 'submitPassword')
verifySeedPhraseSpy = sinon.spy(background, 'verifySeedPhrase')
return store.dispatch(actions.tryUnlockMetamask())
.then(() => {
assert(submitPasswordSpy.calledOnce)
assert(verifySeedPhraseSpy.calledOnce)
})
await store.dispatch(actions.tryUnlockMetamask())
assert(submitPasswordSpy.calledOnce)
assert(verifySeedPhraseSpy.calledOnce)
})
it('errors on submitPassword will fail', async () => {
@ -193,15 +193,17 @@ describe('Actions', () => {
describe('#requestRevealSeedWords', () => {
let submitPasswordSpy
it('calls submitPassword in background', () => {
afterEach(() => {
submitPasswordSpy.restore()
})
it('calls submitPassword in background', async () => {
const store = mockStore()
submitPasswordSpy = sinon.spy(background, 'verifySeedPhrase')
return store.dispatch(actions.requestRevealSeedWords())
.then(() => {
assert(submitPasswordSpy.calledOnce)
})
await store.dispatch(actions.requestRevealSeedWords())
assert(submitPasswordSpy.calledOnce)
})
it('displays warning error message then callback in background errors', async () => {
@ -235,8 +237,9 @@ describe('Actions', () => {
removeAccountSpy.restore()
})
it('calls removeAccount in background and expect actions to show account', () => {
it('calls removeAccount in background and expect actions to show account', async () => {
const store = mockStore(devState)
const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
{ type: 'HIDE_LOADING_INDICATION' },
@ -245,20 +248,20 @@ describe('Actions', () => {
removeAccountSpy = sinon.spy(background, 'removeAccount')
return store.dispatch(actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc'))
.then(() => {
assert(removeAccountSpy.calledOnce)
assert.deepEqual(store.getActions(), expectedActions)
})
await store.dispatch(actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc'))
assert(removeAccountSpy.calledOnce)
assert.deepEqual(store.getActions(), expectedActions)
})
it('displays warning error message when removeAccount callback errors', async () => {
const store = mockStore()
const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
{ type: 'HIDE_LOADING_INDICATION' },
{ type: 'DISPLAY_WARNING', value: 'error' },
]
removeAccountSpy = sinon.stub(background, 'removeAccount')
removeAccountSpy.callsFake((_, callback) => {
callback(new Error('error'))
@ -331,11 +334,9 @@ describe('Actions', () => {
resetAccountSpy = sinon.spy(background, 'resetAccount')
return store.dispatch(actions.resetAccount())
.then(() => {
assert(resetAccountSpy.calledOnce)
assert.deepEqual(store.getActions(), expectedActions)
})
await store.dispatch(actions.resetAccount())
assert(resetAccountSpy.calledOnce)
assert.deepEqual(store.getActions(), expectedActions)
})
it('throws if resetAccount throws', async () => {
@ -376,10 +377,8 @@ describe('Actions', () => {
const importPrivkey = 'c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3'
return store.dispatch(actions.importNewAccount('Private Key', [ importPrivkey ]))
.then(() => {
assert(importAccountWithStrategySpy.calledOnce)
})
store.dispatch(actions.importNewAccount('Private Key', [ importPrivkey ]))
assert(importAccountWithStrategySpy.calledOnce)
})
it('displays warning error message when importAccount in background callback errors', async () => {
@ -407,21 +406,181 @@ describe('Actions', () => {
describe('#addNewAccount', () => {
let addNewAccountSpy
it('Adds a new account', () => {
const store = mockStore({ metamask: devState })
const addNewAccountSpy = sinon.spy(background, 'addNewAccount')
store.dispatch(actions.addNewAccount())
assert(addNewAccountSpy.calledOnce)
})
})
describe('#checkHardwareStatus', () => {
let checkHardwareStatusSpy
beforeEach(() => {
checkHardwareStatusSpy = sinon.stub(background, 'checkHardwareStatus')
})
afterEach(() => {
addNewAccountSpy.restore()
checkHardwareStatusSpy.restore()
})
it('Adds a new account', () => {
const store = mockStore({ metamask: devState })
it('calls checkHardwareStatus in background', async () => {
const store = mockStore()
store.dispatch(await actions.checkHardwareStatus('ledger', `m/44'/60'/0'/0`))
assert.equal(checkHardwareStatusSpy.calledOnce, true)
})
it('shows loading indicator and displays error', async () => {
const store = mockStore()
const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
{ type: 'DISPLAY_WARNING', value: 'error' },
]
checkHardwareStatusSpy.callsFake((deviceName, hdPath, callback) => {
callback(new Error('error'))
})
try {
await store.dispatch(actions.checkHardwareStatus())
assert.fail('Should have thrown error')
} catch (_) {
assert.deepEqual(store.getActions(), expectedActions)
}
})
})
describe('#forgetDevice', () => {
let forgetDeviceSpy
beforeEach(() => {
forgetDeviceSpy = sinon.stub(background, 'forgetDevice')
})
afterEach(() => {
forgetDeviceSpy.restore()
})
it('calls forgetDevice in background', () => {
const store = mockStore()
store.dispatch(actions.forgetDevice('ledger'))
assert.equal(forgetDeviceSpy.calledOnce, true)
})
it('shows loading indicator and displays error', async () => {
const store = mockStore()
const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
{ type: 'DISPLAY_WARNING', value: 'error' },
]
forgetDeviceSpy.callsFake((deviceName, callback) => {
callback(new Error('error'))
})
try {
await store.dispatch(actions.forgetDevice())
assert.fail('Should have thrown error')
} catch (_) {
assert.deepEqual(store.getActions(), expectedActions)
}
})
})
describe('#connectHardware', () => {
let connectHardwareSpy
beforeEach(() => {
connectHardwareSpy = sinon.stub(background, 'connectHardware')
})
afterEach(() => {
connectHardwareSpy.restore()
})
it('calls connectHardware in background', () => {
const store = mockStore()
store.dispatch(actions.connectHardware('ledger', 0, `m/44'/60'/0'/0`))
assert.equal(connectHardwareSpy.calledOnce, true)
})
it('shows loading indicator and displays error', async () => {
const store = mockStore()
const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
{ type: 'DISPLAY_WARNING', value: 'error' },
]
addNewAccountSpy = sinon.spy(background, 'addNewAccount')
connectHardwareSpy.callsFake((deviceName, page, hdPath, callback) => {
callback(new Error('error'))
})
return store.dispatch(actions.addNewAccount())
.then(() => {
assert(addNewAccountSpy.calledOnce)
})
try {
await store.dispatch(actions.connectHardware())
assert.fail('Should have thrown error')
} catch (_) {
assert.deepEqual(store.getActions(), expectedActions)
}
})
})
describe('#unlockHardwareWalletAccount', () => {
let unlockHardwareWalletAccountSpy
beforeEach(() => {
unlockHardwareWalletAccountSpy = sinon.stub(background, 'unlockHardwareWalletAccount')
})
afterEach(() => {
unlockHardwareWalletAccountSpy.restore()
})
it('calls unlockHardwareWalletAccount in background', () => {
const store = mockStore()
store.dispatch(actions.unlockHardwareWalletAccount('ledger', 0, `m/44'/60'/0'/0`))
assert.equal(unlockHardwareWalletAccountSpy.calledOnce, true)
})
it('shows loading indicator and displays error', async() => {
const store = mockStore()
const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
{ type: 'DISPLAY_WARNING', value: 'error' },
]
unlockHardwareWalletAccountSpy.callsFake((deviceName, page, hdPath, callback) => {
callback(new Error('error'))
})
try {
await store.dispatch(actions.unlockHardwareWalletAccount())
assert.fail('Should have thrown error')
} catch (error) {
assert.deepEqual(store.getActions(), expectedActions)
}
})
})
@ -485,11 +644,8 @@ describe('Actions', () => {
const store = mockStore()
signMessageSpy = sinon.spy(background, 'signMessage')
return store.dispatch(actions.signMsg(msgParams))
.then(() => {
assert(signMessageSpy.calledOnce)
})
store.dispatch(actions.signMsg(msgParams))
assert(signMessageSpy.calledOnce)
})
@ -543,10 +699,8 @@ describe('Actions', () => {
signPersonalMessageSpy = sinon.spy(background, 'signPersonalMessage')
return store.dispatch(actions.signPersonalMsg(msgParams))
.then(() => {
assert(signPersonalMessageSpy.calledOnce)
})
store.dispatch(actions.signPersonalMsg(msgParams))
assert(signPersonalMessageSpy.calledOnce)
})
@ -574,12 +728,100 @@ describe('Actions', () => {
})
describe('#signTypedMsg', () => {
let signTypedMsgSpy, messages, typedMessages, msgId
const msgParamsV3 = {
from: '0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc',
data: JSON.stringify({
'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 Mainl',
'version': '1',
'chainId': 1,
'verifyingContract': '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
},
'message': {
'from': {
'name': 'Cow',
'wallet': '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
},
'to': {
'name': 'Bob',
'wallet': '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
'contents': 'Hello, Bob!',
},
}),
}
beforeEach(() => {
metamaskController.newUnsignedTypedMessage(msgParamsV3, 'V3')
messages = metamaskController.typedMessageManager.getUnapprovedMsgs()
typedMessages = metamaskController.typedMessageManager.messages
msgId = Object.keys(messages)[0]
typedMessages[0].msgParams.metamaskId = parseInt(msgId)
})
afterEach(() => {
signTypedMsgSpy.restore()
})
it('calls signTypedMsg in background with no error', async () => {
const store = mockStore()
signTypedMsgSpy = sinon.spy(background, 'signTypedMessage')
await store.dispatch(actions.signTypedMsg(msgParamsV3))
assert(signTypedMsgSpy.calledOnce)
})
it('returns expected actions with error', async () => {
const store = mockStore()
const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
{ type: 'UPDATE_METAMASK_STATE', value: undefined },
{ type: 'HIDE_LOADING_INDICATION' },
{ type: 'DISPLAY_WARNING', value: 'error' },
]
signTypedMsgSpy = sinon.stub(background, 'signTypedMessage')
signTypedMsgSpy.callsFake((_, callback) => {
callback(new Error('error'))
})
try {
await store.dispatch(actions.signTypedMsg())
assert.fail('Should have thrown error')
} catch (_) {
assert.deepEqual(store.getActions(), expectedActions)
}
})
})
describe('#signTx', () => {
let sendTransactionSpy
beforeEach(() => {
global.ethQuery = new EthQuery(provider)
sendTransactionSpy = sinon.stub(global.ethQuery, 'sendTransaction')
})
@ -589,6 +831,7 @@ describe('Actions', () => {
it('calls sendTransaction in global ethQuery', () => {
const store = mockStore()
store.dispatch(actions.signTx())
assert(sendTransactionSpy.calledOnce)
})
@ -608,6 +851,71 @@ describe('Actions', () => {
})
})
describe('#updatedGasData', () => {
it('errors when get code does not return', async () => {
const store = mockStore()
const expectedActions = [
{ type: 'GAS_LOADING_STARTED' },
{ type: 'UPDATE_SEND_ERRORS', value: { gasLoadingError: 'gasLoadingError' } },
{ type: 'GAS_LOADING_FINISHED' },
]
const mockData = {
gasPrice: '0x3b9aca00', //
blockGasLimit: '0x6ad79a', // 7002010
selectedAddress: '0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc',
to: '0xEC1Adf982415D2Ef5ec55899b9Bfb8BC0f29251B',
value: '0xde0b6b3a7640000', // 1000000000000000000
}
try {
await store.dispatch(actions.updateGasData(mockData))
assert.fail('Should have thrown error')
} catch (error) {
assert.deepEqual(store.getActions(), expectedActions)
}
})
})
describe('#updatedGasData', () => {
const stub = sinon.stub().returns('0x')
const mockData = {
gasPrice: '0x3b9aca00', //
blockGasLimit: '0x6ad79a', // 7002010
selectedAddress: '0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc',
to: '0xEC1Adf982415D2Ef5ec55899b9Bfb8BC0f29251B',
value: '0xde0b6b3a7640000', // 1000000000000000000
}
beforeEach(() => {
global.eth = {
getCode: stub,
}
})
afterEach(() => {
stub.reset()
})
it('returns default gas limit for basic eth transaction', async () => {
const store = mockStore()
const expectedActions = [
{ type: 'GAS_LOADING_STARTED' },
{ type: 'UPDATE_GAS_LIMIT', value: '0x5208' },
{ type: 'metamask/gas/SET_CUSTOM_GAS_LIMIT', value: '0x5208' },
{ type: 'UPDATE_SEND_ERRORS', value: { gasLoadingError: null } },
{ type: 'GAS_LOADING_FINISHED' },
]
await store.dispatch(actions.updateGasData(mockData))
assert.deepEqual(store.getActions(), expectedActions)
})
})
describe('#signTokenTx', () => {
let tokenSpy
@ -628,6 +936,61 @@ describe('Actions', () => {
})
})
describe('#updateTransaction', () => {
let updateTransactionSpy, updateTransactionParamsSpy
const txParams = {
'from': '0x1',
'gas': '0x5208',
'gasPrice': '0x3b9aca00',
'to': '0x2',
'value': '0x0',
}
const txData = { id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: txParams }
beforeEach( async () => {
await metamaskController.txController.txStateManager.addTx(txData)
})
afterEach(() => {
updateTransactionSpy.restore()
updateTransactionParamsSpy.restore()
})
it('updates transaction', async () => {
const store = mockStore()
updateTransactionSpy = sinon.spy(background, 'updateTransaction')
updateTransactionParamsSpy = sinon.spy(actions, 'updateTransactionParams')
const result = [ txData.id, txParams ]
await store.dispatch(actions.updateTransaction(txData))
assert(updateTransactionSpy.calledOnce)
assert(updateTransactionParamsSpy.calledOnce)
assert.deepEqual(updateTransactionParamsSpy.args[0], result)
})
it('rejects with error message', async () => {
const store = mockStore()
updateTransactionSpy = sinon.stub(background, 'updateTransaction')
updateTransactionSpy.callsFake((res, callback) => {
callback(new Error('error'))
})
try {
await store.dispatch(actions.updateTransaction(txData))
assert.fail('Should have thrown error')
} catch (error) {
assert.equal(error.message, 'error')
}
})
})
describe('#lockMetamask', () => {
let backgroundSetLockedSpy
@ -635,18 +998,16 @@ describe('Actions', () => {
backgroundSetLockedSpy.restore()
})
it('calls setLocked', () => {
it('calls setLocked', async () => {
const store = mockStore()
backgroundSetLockedSpy = sinon.spy(background, 'setLocked')
return store.dispatch(actions.lockMetamask())
.then(() => {
assert(backgroundSetLockedSpy.calledOnce)
})
await store.dispatch(actions.lockMetamask())
assert(backgroundSetLockedSpy.calledOnce)
})
it('returns display warning error with value when setLocked in background callback errors', () => {
it('returns display warning error with value when setLocked in background callback errors', async () => {
const store = mockStore()
const expectedActions = [
@ -660,10 +1021,13 @@ describe('Actions', () => {
callback(new Error('error'))
})
return store.dispatch(actions.lockMetamask())
.then(() => {
assert.deepEqual(store.getActions(), expectedActions)
})
try {
await store.dispatch(actions.lockMetamask())
assert.fail('Should have thrown error')
} catch (error) {
assert.deepEqual(store.getActions(), expectedActions)
}
})
})
@ -748,13 +1112,11 @@ describe('Actions', () => {
addTokenSpy.restore()
})
it('calls addToken in background', () => {
it('calls addToken in background', async () => {
const store = mockStore()
store.dispatch(actions.addToken())
.then(() => {
assert(addTokenSpy.calledOnce)
})
assert(addTokenSpy.calledOnce)
})
it('errors when addToken in background throws', async () => {
@ -790,12 +1152,10 @@ describe('Actions', () => {
removeTokenSpy.restore()
})
it('calls removeToken in background', () => {
it('calls removeToken in background', async () => {
const store = mockStore()
store.dispatch(actions.removeToken())
.then(() => {
assert(removeTokenSpy.calledOnce)
})
store.dispatch(await actions.removeToken())
assert(removeTokenSpy.calledOnce)
})
it('errors when removeToken in background fails', async () => {
@ -910,7 +1270,7 @@ describe('Actions', () => {
exportAccountSpy.restore()
})
it('returns expected actions for successful action', () => {
it('returns expected actions for successful action', async () => {
const store = mockStore(devState)
const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
@ -921,12 +1281,10 @@ describe('Actions', () => {
submitPasswordSpy = sinon.spy(background, 'submitPassword')
exportAccountSpy = sinon.spy(background, 'exportAccount')
return store.dispatch(actions.exportAccount(password, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'))
.then(() => {
assert(submitPasswordSpy.calledOnce)
assert(exportAccountSpy.calledOnce)
assert.deepEqual(store.getActions(), expectedActions)
})
await store.dispatch(actions.exportAccount(password, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'))
assert(submitPasswordSpy.calledOnce)
assert(exportAccountSpy.calledOnce)
assert.deepEqual(store.getActions(), expectedActions)
})
it('returns action errors when first func callback errors', async () => {
@ -1082,9 +1440,7 @@ describe('Actions', () => {
getTransactionCountSpy = sinon.spy(global.ethQuery, 'getTransactionCount')
store.dispatch(actions.updateNetworkNonce())
.then(() => {
assert(getTransactionCountSpy.calledOnce)
})
assert(getTransactionCountSpy.calledOnce)
})
it('errors when getTransactionCount throws', async () => {
@ -1155,7 +1511,7 @@ describe('Actions', () => {
fetchMock.restore()
})
it('calls expected actions', () => {
it('calls expected actions', async () => {
const store = mockStore()
setCurrentLocaleSpy = sinon.spy(background, 'setCurrentLocale')
@ -1165,14 +1521,12 @@ describe('Actions', () => {
{ type: 'HIDE_LOADING_INDICATION' },
]
return store.dispatch(actions.updateCurrentLocale('en'))
.then(() => {
assert(setCurrentLocaleSpy.calledOnce)
assert.deepEqual(store.getActions(), expectedActions)
})
await store.dispatch(actions.updateCurrentLocale('en'))
assert(setCurrentLocaleSpy.calledOnce)
assert.deepEqual(store.getActions(), expectedActions)
})
it('calls expected actions', () => {
it('errors when setCurrentLocale throws', async () => {
const store = mockStore()
const expectedActions = [
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
@ -1184,48 +1538,54 @@ describe('Actions', () => {
callback(new Error('error'))
})
return store.dispatch(actions.updateCurrentLocale('en'))
.then(() => {
assert.deepEqual(store.getActions(), expectedActions)
})
try {
await store.dispatch(actions.updateCurrentLocale('en'))
assert.fail('Should have thrown error')
} catch (_) {
assert.deepEqual(store.getActions(), expectedActions)
}
})
})
describe('#markPasswordForgotten', () => {
let markPasswordForgottenSpy
let markPasswordForgottenSpy, forgotPasswordSpy
beforeEach(() => {
markPasswordForgottenSpy = sinon.stub(background, 'markPasswordForgotten')
markPasswordForgottenSpy = sinon.spy(background, 'markPasswordForgotten')
forgotPasswordSpy = sinon.spy(actions, 'forgotPassword')
})
afterEach(() => {
markPasswordForgottenSpy.restore()
forgotPasswordSpy.restore()
})
it('calls markPasswordForgotten', () => {
const store = mockStore()
store.dispatch(actions.markPasswordForgotten())
assert(forgotPasswordSpy.calledOnce)
assert(markPasswordForgottenSpy.calledOnce)
})
})
describe('#unMarkPasswordForgotten', () => {
let unMarkPasswordForgottenSpy
let unMarkPasswordForgottenSpy, forgotPasswordSpy
beforeEach(() => {
unMarkPasswordForgottenSpy = sinon.stub(background, 'unMarkPasswordForgotten')
unMarkPasswordForgottenSpy = sinon.stub(background, 'unMarkPasswordForgotten').returns(forgotPasswordSpy)
forgotPasswordSpy = sinon.spy(actions, 'forgotPassword')
})
afterEach(() => {
unMarkPasswordForgottenSpy.restore()
forgotPasswordSpy.restore()
})
it('calls unMarkPasswordForgotten', () => {
it('calls unMarkPasswordForgotten', async () => {
const store = mockStore()
store.dispatch(actions.unMarkPasswordForgotten())
store.dispatch(await actions.unMarkPasswordForgotten())
assert(unMarkPasswordForgottenSpy.calledOnce)
})
})
})

Loading…
Cancel
Save