aboutsummaryrefslogtreecommitdiffstats
path: root/test/unit/ui
diff options
context:
space:
mode:
authorThomas Huang <tmashuang@users.noreply.github.com>2018-10-10 22:32:26 +0800
committerkumavis <kumavis@users.noreply.github.com>2018-10-10 22:32:26 +0800
commitb45479934dadd8a4177b51b81732ab15f3226b93 (patch)
tree8a0976496054c278e2014711ef7c4f289b26ad2e /test/unit/ui
parent70fc093b21f733b182654c38e51b14c6bf726cbc (diff)
downloadtangerine-wallet-browser-b45479934dadd8a4177b51b81732ab15f3226b93.tar
tangerine-wallet-browser-b45479934dadd8a4177b51b81732ab15f3226b93.tar.gz
tangerine-wallet-browser-b45479934dadd8a4177b51b81732ab15f3226b93.tar.bz2
tangerine-wallet-browser-b45479934dadd8a4177b51b81732ab15f3226b93.tar.lz
tangerine-wallet-browser-b45479934dadd8a4177b51b81732ab15f3226b93.tar.xz
tangerine-wallet-browser-b45479934dadd8a4177b51b81732ab15f3226b93.tar.zst
tangerine-wallet-browser-b45479934dadd8a4177b51b81732ab15f3226b93.zip
test - add actions unit tests (#5369)
* Actions.spec.js * Error handling tests * Lint
Diffstat (limited to 'test/unit/ui')
-rw-r--r--test/unit/ui/app/actions.spec.js1468
1 files changed, 1468 insertions, 0 deletions
diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js
new file mode 100644
index 000000000..748a58b32
--- /dev/null
+++ b/test/unit/ui/app/actions.spec.js
@@ -0,0 +1,1468 @@
+// Used to inspect long objects
+// util.inspect({JSON}, false, null))
+// const util = require('util')
+const assert = require('assert')
+const sinon = require('sinon')
+const clone = require('clone')
+const nock = require('nock')
+const fetchMock = require('fetch-mock')
+const configureStore = require('redux-mock-store').default
+const thunk = require('redux-thunk').default
+const EthQuery = require('eth-query')
+const Eth = require('ethjs')
+const KeyringController = require('eth-keyring-controller')
+
+const { createTestProviderTools } = require('../../../stub/provider')
+const provider = createTestProviderTools({ scaffold: {}}).provider
+
+const enLocale = require('../../../../app/_locales/en/messages.json')
+const actions = require('../../../../ui/app/actions')
+const MetaMaskController = require('../../../../app/scripts/metamask-controller')
+
+const firstTimeState = require('../../../unit/localhostState')
+const devState = require('../../../data/2-state.json')
+
+const middleware = [thunk]
+const mockStore = configureStore(middleware)
+
+describe('Actions', () => {
+
+ const noop = () => {}
+
+ let background, metamaskController
+
+ const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'
+ const password = 'a-fake-password'
+ const importPrivkey = '4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553'
+
+ beforeEach(async () => {
+
+
+ metamaskController = new MetaMaskController({
+ provider,
+ keyringController: new KeyringController({}),
+ showUnapprovedTx: noop,
+ showUnconfirmedMessage: noop,
+ encryptor: {
+ encrypt: function (password, object) {
+ this.object = object
+ return Promise.resolve('mock-encrypted')
+ },
+ decrypt: function () {
+ return Promise.resolve(this.object)
+ },
+ },
+ initState: clone(firstTimeState),
+ })
+
+ await metamaskController.createNewVaultAndRestore(password, TEST_SEED)
+
+ await metamaskController.importAccountWithStrategy('Private Key', [ importPrivkey ])
+
+ background = metamaskController.getApi()
+
+ actions._setBackgroundConnection(background)
+
+ global.ethQuery = new EthQuery(provider)
+ })
+
+ describe('#tryUnlockMetamask', () => {
+
+ let submitPasswordSpy, verifySeedPhraseSpy
+
+ afterEach(() => {
+ submitPasswordSpy.restore()
+ verifySeedPhraseSpy.restore()
+ })
+
+ it('', async () => {
+
+ const store = mockStore({})
+
+ submitPasswordSpy = sinon.spy(background, 'submitPassword')
+ verifySeedPhraseSpy = sinon.spy(background, 'verifySeedPhrase')
+
+ return store.dispatch(actions.tryUnlockMetamask())
+ .then(() => {
+ assert(submitPasswordSpy.calledOnce)
+ assert(verifySeedPhraseSpy.calledOnce)
+ })
+ })
+
+ it('errors on submitPassword will fail', () => {
+
+ const store = mockStore({})
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'UNLOCK_IN_PROGRESS' },
+ { type: 'UNLOCK_FAILED', value: 'error in submitPassword' },
+ { type: 'HIDE_LOADING_INDICATION' },
+ ]
+
+
+ submitPasswordSpy = sinon.stub(background, 'submitPassword')
+
+ submitPasswordSpy.callsFake((password, callback) => {
+ callback(new Error('error in submitPassword'))
+ })
+
+ return store.dispatch(actions.tryUnlockMetamask('test'))
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ it('displays warning error and unlock failed when verifySeed fails', () => {
+ const store = mockStore({})
+ const displayWarningError = [ { type: 'DISPLAY_WARNING', value: 'error' } ]
+ const unlockFailedError = [ { type: 'UNLOCK_FAILED', value: 'error' } ]
+
+ verifySeedPhraseSpy = sinon.stub(background, 'verifySeedPhrase')
+ verifySeedPhraseSpy.callsFake(callback => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.tryUnlockMetamask('test'))
+ .catch(() => {
+ const actions = store.getActions()
+ const warning = actions.filter(action => action.type === 'DISPLAY_WARNING')
+ const unlockFailed = actions.filter(action => action.type === 'UNLOCK_FAILED')
+ assert.deepEqual(warning, displayWarningError)
+ assert.deepEqual(unlockFailed, unlockFailedError)
+ })
+ })
+ })
+
+ describe('#confirmSeedWords', () => {
+
+ let clearSeedWordCacheSpy
+
+ afterEach(() => {
+ clearSeedWordCacheSpy.restore()
+ })
+
+ it('shows account page after clearing seed word cache', () => {
+
+ const store = mockStore({})
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'SHOW_ACCOUNTS_PAGE' },
+ ]
+
+ clearSeedWordCacheSpy = sinon.spy(background, 'clearSeedWordCache')
+
+ return store.dispatch(actions.confirmSeedWords())
+ .then(() => {
+ assert.equal(clearSeedWordCacheSpy.callCount, 1)
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ it('errors in callback will display warning', () => {
+ const store = mockStore({})
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ clearSeedWordCacheSpy = sinon.stub(background, 'clearSeedWordCache')
+
+ clearSeedWordCacheSpy.callsFake((callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.confirmSeedWords())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#createNewVaultAndRestore', () => {
+
+ let createNewVaultAndRestoreSpy, clearSeedWordCacheSpy
+
+ afterEach(() => {
+ createNewVaultAndRestoreSpy.restore()
+ })
+
+ it('clears seed words and restores new vault', () => {
+
+ const store = mockStore({})
+
+ createNewVaultAndRestoreSpy = sinon.spy(background, 'createNewVaultAndRestore')
+ clearSeedWordCacheSpy = sinon.spy(background, 'clearSeedWordCache')
+ return store.dispatch(actions.createNewVaultAndRestore())
+ .then(() => {
+ assert(clearSeedWordCacheSpy.calledOnce)
+ assert(createNewVaultAndRestoreSpy.calledOnce)
+ })
+ })
+
+ it('errors when callback in clearSeedWordCache throws', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ { type: 'HIDE_LOADING_INDICATION' },
+ ]
+
+ clearSeedWordCacheSpy = sinon.stub(background, 'clearSeedWordCache')
+ clearSeedWordCacheSpy.callsFake((callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.createNewVaultAndRestore())
+ .then(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ it('errors when callback in createNewVaultAndRestore throws', () => {
+
+ const store = mockStore({})
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ { type: 'HIDE_LOADING_INDICATION' },
+ ]
+
+ createNewVaultAndRestoreSpy = sinon.stub(background, 'createNewVaultAndRestore')
+
+ createNewVaultAndRestoreSpy.callsFake((password, seed, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.createNewVaultAndRestore())
+ .then(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#createNewVaultAndKeychain', () => {
+
+ let createNewVaultAndKeychainSpy, placeSeedWordsSpy
+
+ afterEach(() => {
+ createNewVaultAndKeychainSpy.restore()
+ placeSeedWordsSpy.restore()
+ })
+
+ it('calls createNewVaultAndKeychain and placeSeedWords in background', () => {
+
+ const store = mockStore()
+
+ createNewVaultAndKeychainSpy = sinon.spy(background, 'createNewVaultAndKeychain')
+ placeSeedWordsSpy = sinon.spy(background, 'placeSeedWords')
+
+ return store.dispatch(actions.createNewVaultAndKeychain())
+ .then(() => {
+ assert(createNewVaultAndKeychainSpy.calledOnce)
+ assert(placeSeedWordsSpy.calledOnce)
+ })
+ })
+
+ it('displays error and value when callback errors', () => {
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ { type: 'HIDE_LOADING_INDICATION' },
+ ]
+
+ createNewVaultAndKeychainSpy = sinon.stub(background, 'createNewVaultAndKeychain')
+ createNewVaultAndKeychainSpy.callsFake((password, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.createNewVaultAndKeychain())
+ .then(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+
+ })
+
+ it('errors when placeSeedWords throws', () => {
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ { type: 'HIDE_LOADING_INDICATION' },
+ ]
+
+ placeSeedWordsSpy = sinon.stub(background, 'placeSeedWords')
+ placeSeedWordsSpy.callsFake((callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.createNewVaultAndKeychain())
+ .then(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#requestRevealSeed', () => {
+
+ let submitPasswordSpy, placeSeedWordsSpy
+
+ afterEach(() => {
+ submitPasswordSpy.restore()
+ })
+
+ it('calls submitPassword and placeSeedWords from background', () => {
+
+ const store = mockStore()
+
+ submitPasswordSpy = sinon.spy(background, 'submitPassword')
+ placeSeedWordsSpy = sinon.spy(background, 'placeSeedWords')
+
+ return store.dispatch(actions.requestRevealSeed())
+ .then(() => {
+ assert(submitPasswordSpy.calledOnce)
+ assert(placeSeedWordsSpy.calledOnce)
+ })
+ })
+
+ it('displays warning error with value when callback errors', () => {
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ submitPasswordSpy = sinon.stub(background, 'submitPassword')
+ submitPasswordSpy.callsFake((password, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.requestRevealSeed())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#requestRevealSeedWords', () => {
+ let submitPasswordSpy
+
+ it('calls submitPassword in background', () => {
+ const store = mockStore()
+
+ submitPasswordSpy = sinon.spy(background, 'verifySeedPhrase')
+
+ return store.dispatch(actions.requestRevealSeedWords())
+ .then(() => {
+ assert(submitPasswordSpy.calledOnce)
+ })
+ })
+
+ it('displays warning error message then callback in background errors', () => {
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ submitPasswordSpy = sinon.stub(background, 'verifySeedPhrase')
+ submitPasswordSpy.callsFake((callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.requestRevealSeedWords())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+
+ })
+ })
+
+ describe('#requestRevealSeed', () => {
+
+ let submitPasswordSpy, placeSeedWordsSpy
+
+ afterEach(() => {
+ submitPasswordSpy.restore()
+ placeSeedWordsSpy.restore()
+ })
+
+ it('calls submitPassword and placeSeedWords in background', () => {
+
+ const store = mockStore()
+
+ submitPasswordSpy = sinon.spy(background, 'submitPassword')
+ placeSeedWordsSpy = sinon.spy(background, 'placeSeedWords')
+
+ return store.dispatch(actions.requestRevealSeed())
+ .then(() => {
+ assert(submitPasswordSpy.calledOnce)
+ assert(placeSeedWordsSpy.calledOnce)
+ })
+ })
+
+ it('displays warning error message when submitPassword in background errors', () => {
+ submitPasswordSpy = sinon.stub(background, 'submitPassword')
+ submitPasswordSpy.callsFake((password, callback) => {
+ callback(new Error('error'))
+ })
+
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ return store.dispatch(actions.requestRevealSeed())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ it('errors when placeSeedWords throw', () => {
+ placeSeedWordsSpy = sinon.stub(background, 'placeSeedWords')
+ placeSeedWordsSpy.callsFake((callback) => {
+ callback(new Error('error'))
+ })
+
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ return store.dispatch(actions.requestRevealSeed())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#removeAccount', () => {
+ let removeAccountSpy
+
+ afterEach(() => {
+ removeAccountSpy.restore()
+ })
+
+ it('calls removeAccount in background and expect actions to show account', () => {
+ const store = mockStore(devState)
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'SHOW_ACCOUNTS_PAGE' },
+ ]
+
+ removeAccountSpy = sinon.spy(background, 'removeAccount')
+
+ return store.dispatch(actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc'))
+ .then(() => {
+ assert(removeAccountSpy.calledOnce)
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ it('displays warning error message when removeAccount callback errors', () => {
+ 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((address, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.removeAccount('0xe18035bf8712672935fdb4e5e431b1a0183d2dfc'))
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+
+ })
+ })
+
+ describe('#addNewKeyring', () => {
+ let addNewKeyringSpy
+
+ beforeEach(() => {
+ addNewKeyringSpy = sinon.stub(background, 'addNewKeyring')
+ })
+
+ afterEach(() => {
+ addNewKeyringSpy.restore()
+ })
+
+ it('', () => {
+ const privateKey = 'c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3'
+
+ const store = mockStore()
+ store.dispatch(actions.addNewKeyring('Simple Key Pair', [ privateKey ]))
+ assert(addNewKeyringSpy.calledOnce)
+ })
+
+ it('errors then addNewKeyring in background throws', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ addNewKeyringSpy.callsFake((type, opts, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.addNewKeyring())
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+
+ })
+
+ describe('#resetAccount', () => {
+
+ let resetAccountSpy
+
+ afterEach(() => {
+ resetAccountSpy.restore()
+ })
+
+ it('', () => {
+
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'SHOW_ACCOUNTS_PAGE' },
+ ]
+
+ resetAccountSpy = sinon.spy(background, 'resetAccount')
+
+ return store.dispatch(actions.resetAccount())
+ .then(() => {
+ assert(resetAccountSpy.calledOnce)
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ it('', () => {
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ resetAccountSpy = sinon.stub(background, 'resetAccount')
+ resetAccountSpy.callsFake((callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.resetAccount())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#importNewAccount', () => {
+
+ let importAccountWithStrategySpy
+
+ afterEach(() => {
+ importAccountWithStrategySpy.restore()
+ })
+
+ it('calls importAccountWithStrategies in background', () => {
+ const store = mockStore()
+
+ importAccountWithStrategySpy = sinon.spy(background, 'importAccountWithStrategy')
+
+ const importPrivkey = 'c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3'
+
+ return store.dispatch(actions.importNewAccount('Private Key', [ importPrivkey ]))
+ .then(() => {
+ assert(importAccountWithStrategySpy.calledOnce)
+ })
+ })
+
+ it('displays warning error message when importAccount in background callback errors', () => {
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: 'This may take a while, please be patient.' },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ importAccountWithStrategySpy = sinon.stub(background, 'importAccountWithStrategy')
+ importAccountWithStrategySpy.callsFake((strategy, args, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.importNewAccount())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#addNewAccount', () => {
+
+ let addNewAccountSpy
+
+ afterEach(() => {
+ addNewAccountSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore({ metamask: devState })
+
+ addNewAccountSpy = sinon.spy(background, 'addNewAccount')
+
+ return store.dispatch(actions.addNewAccount())
+ .then(() => {
+ assert(addNewAccountSpy.calledOnce)
+ })
+ })
+ })
+
+ describe('#setCurrentCurrency', () => {
+
+ let setCurrentCurrencySpy
+
+ beforeEach(() => {
+ setCurrentCurrencySpy = sinon.stub(background, 'setCurrentCurrency')
+ })
+
+ afterEach(() => {
+ setCurrentCurrencySpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+
+ store.dispatch(actions.setCurrentCurrency('jpy'))
+ assert(setCurrentCurrencySpy.calledOnce)
+ })
+
+ it('', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+ setCurrentCurrencySpy.callsFake((currencyCode, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.setCurrentCurrency())
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ describe('#signMsg', () => {
+
+ let signMessageSpy, metamaskMsgs, msgId, messages
+
+ const msgParams = {
+ from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
+ data: '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0',
+ }
+
+ beforeEach(() => {
+ metamaskController.newUnsignedMessage(msgParams, noop)
+ metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs()
+ messages = metamaskController.messageManager.messages
+ msgId = Object.keys(metamaskMsgs)[0]
+ messages[0].msgParams.metamaskId = parseInt(msgId)
+ })
+
+ afterEach(() => {
+ signMessageSpy.restore()
+ })
+
+ it('calls signMsg in background', () => {
+ const store = mockStore()
+
+ signMessageSpy = sinon.spy(background, 'signMessage')
+
+ return store.dispatch(actions.signMsg(msgParams))
+ .then(() => {
+ assert(signMessageSpy.calledOnce)
+ })
+
+ })
+
+ it('errors when signMessage in background throws', () => {
+ 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' },
+ ]
+
+ signMessageSpy = sinon.stub(background, 'signMessage')
+ signMessageSpy.callsFake((msgData, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.signMsg())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ })
+
+ describe('#signPersonalMsg', () => {
+
+ let signPersonalMessageSpy, metamaskMsgs, msgId, personalMessages
+
+ const msgParams = {
+ from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
+ data: '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0',
+ }
+
+ beforeEach(() => {
+ metamaskController.newUnsignedPersonalMessage(msgParams, noop)
+ metamaskMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs()
+ personalMessages = metamaskController.personalMessageManager.messages
+ msgId = Object.keys(metamaskMsgs)[0]
+ personalMessages[0].msgParams.metamaskId = parseInt(msgId)
+ })
+
+ afterEach(() => {
+ signPersonalMessageSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+
+ signPersonalMessageSpy = sinon.spy(background, 'signPersonalMessage')
+
+ return store.dispatch(actions.signPersonalMsg(msgParams))
+ .then(() => {
+ assert(signPersonalMessageSpy.calledOnce)
+ })
+
+ })
+
+ it('', () => {
+ 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' },
+ ]
+
+ signPersonalMessageSpy = sinon.stub(background, 'signPersonalMessage')
+ signPersonalMessageSpy.callsFake((msgData, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.signPersonalMsg(msgParams))
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ })
+
+ describe('#signTx', () => {
+
+ let sendTransactionSpy
+
+ beforeEach(() => {
+ global.ethQuery = new EthQuery(provider)
+ sendTransactionSpy = sinon.stub(global.ethQuery, 'sendTransaction')
+ })
+
+ afterEach(() => {
+ sendTransactionSpy.restore()
+ })
+
+ it('calls sendTransaction in global ethQuery', () => {
+ const store = mockStore()
+ store.dispatch(actions.signTx())
+ assert(sendTransactionSpy.calledOnce)
+ })
+
+ it('errors in when sendTransaction throws', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ { type: 'SHOW_CONF_TX_PAGE', transForward: true, id: undefined },
+ ]
+ sendTransactionSpy.callsFake((txData, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.signTx())
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ describe('#signTokenTx', () => {
+
+ let tokenSpy
+
+ beforeEach(() => {
+ global.eth = new Eth(provider)
+ tokenSpy = sinon.spy(global.eth, 'contract')
+ })
+
+ afterEach(() => {
+ tokenSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+ store.dispatch(actions.signTokenTx())
+ assert(tokenSpy.calledOnce)
+ })
+ })
+
+ describe('#lockMetamask', () => {
+ let backgroundSetLockedSpy
+
+ afterEach(() => {
+ backgroundSetLockedSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+
+ backgroundSetLockedSpy = sinon.spy(background, 'setLocked')
+
+ return store.dispatch(actions.lockMetamask())
+ .then(() => {
+ assert(backgroundSetLockedSpy.calledOnce)
+ })
+ })
+
+ it('returns display warning error with value when setLocked in background callback errors', () => {
+ const store = mockStore()
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'LOCK_METAMASK' },
+ ]
+ backgroundSetLockedSpy = sinon.stub(background, 'setLocked')
+ backgroundSetLockedSpy.callsFake(callback => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.lockMetamask())
+ .then(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#setSelectedAddress', () => {
+ let setSelectedAddressSpy
+
+ beforeEach(() => {
+ setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress')
+ })
+
+ afterEach(() => {
+ setSelectedAddressSpy.restore()
+ })
+
+ it('calls setSelectedAddress in background', () => {
+ const store = mockStore({ metamask: devState })
+
+ store.dispatch(actions.setSelectedAddress('0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'))
+ assert(setSelectedAddressSpy.calledOnce)
+ })
+
+ it('errors when setSelectedAddress throws', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ setSelectedAddressSpy.callsFake((address, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.setSelectedAddress())
+ assert.deepEqual(store.getActions(), expectedActions)
+
+ })
+ })
+
+ describe('#showAccountDetail', () => {
+ let setSelectedAddressSpy
+
+ beforeEach(() => {
+ setSelectedAddressSpy = sinon.stub(background, 'setSelectedAddress')
+ })
+
+ afterEach(() => {
+ setSelectedAddressSpy.restore()
+ })
+
+ it('#showAccountDetail', () => {
+ const store = mockStore()
+
+ store.dispatch(actions.showAccountDetail())
+ assert(setSelectedAddressSpy.calledOnce)
+ })
+
+ it('', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+ setSelectedAddressSpy.callsFake((address, callback) => {
+ callback(new Error('error'))
+ })
+
+
+ store.dispatch(actions.showAccountDetail())
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ describe('#addToken', () => {
+ let addTokenSpy
+
+ beforeEach(() => {
+ addTokenSpy = sinon.stub(background, 'addToken')
+ })
+
+ afterEach(() => {
+ addTokenSpy.restore()
+ })
+
+ it('calls addToken in background', () => {
+ const store = mockStore()
+
+ store.dispatch(actions.addToken())
+ .then(() => {
+ assert(addTokenSpy.calledOnce)
+ })
+ })
+
+ it('errors when addToken in background throws', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ { type: 'UPDATE_TOKENS', newTokens: undefined },
+ ]
+
+ addTokenSpy.callsFake((address, symbol, decimals, image, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.addToken())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#removeToken', () => {
+
+ let removeTokenSpy
+
+ beforeEach(() => {
+ removeTokenSpy = sinon.stub(background, 'removeToken')
+ })
+
+ afterEach(() => {
+ removeTokenSpy.restore()
+ })
+
+ it('calls removeToken in background', () => {
+ const store = mockStore()
+ store.dispatch(actions.removeToken())
+ .then(() => {
+ assert(removeTokenSpy.calledOnce)
+ })
+ })
+
+ it('errors when removeToken in background fails', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ { type: 'UPDATE_TOKENS', newTokens: undefined },
+ ]
+
+ removeTokenSpy.callsFake((address, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.removeToken())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#markNoticeRead', () => {
+ let markNoticeReadSpy
+ const notice = {
+ id: 0,
+ read: false,
+ date: 'test date',
+ title: 'test title',
+ body: 'test body',
+ }
+
+ beforeEach(() => {
+ markNoticeReadSpy = sinon.stub(background, 'markNoticeRead')
+ })
+
+ afterEach(() => {
+ markNoticeReadSpy.restore()
+ })
+
+ it('calls markNoticeRead in background', () => {
+ const store = mockStore()
+
+ store.dispatch(actions.markNoticeRead(notice))
+ .then(() => {
+ assert(markNoticeReadSpy.calledOnce)
+ })
+
+ })
+
+ it('errors when markNoticeRead in background throws', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+ markNoticeReadSpy.callsFake((notice, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.markNoticeRead())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#setProviderType', () => {
+ let setProviderTypeSpy
+
+ beforeEach(() => {
+ setProviderTypeSpy = sinon.stub(background, 'setProviderType')
+ })
+
+ afterEach(() => {
+ setProviderTypeSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+ store.dispatch(actions.setProviderType())
+ assert(setProviderTypeSpy.calledOnce)
+ })
+
+ it('', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' },
+ ]
+
+ setProviderTypeSpy.callsFake((type, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.setProviderType())
+ assert(setProviderTypeSpy.calledOnce)
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ describe('#setRpcTarget', () => {
+ let setRpcTargetSpy
+
+ beforeEach(() => {
+ setRpcTargetSpy = sinon.stub(background, 'setCustomRpc')
+ })
+
+ afterEach(() => {
+ setRpcTargetSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+ store.dispatch(actions.setRpcTarget('http://localhost:8545'))
+ assert(setRpcTargetSpy.calledOnce)
+ })
+
+ it('', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'DISPLAY_WARNING', value: 'Had a problem changing networks!' },
+ ]
+
+ setRpcTargetSpy.callsFake((newRpc, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.setRpcTarget())
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ describe('#addToAddressBook', () => {
+ let addToAddressBookSpy
+
+ beforeEach(() => {
+ addToAddressBookSpy = sinon.stub(background, 'setAddressBook')
+ })
+
+ afterEach(() => {
+ addToAddressBookSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+ store.dispatch(actions.addToAddressBook('test'))
+ assert(addToAddressBookSpy.calledOnce)
+ })
+ })
+
+ describe('#exportAccount', () => {
+ let submitPasswordSpy, exportAccountSpy
+
+ afterEach(() => {
+ submitPasswordSpy.restore()
+ exportAccountSpy.restore()
+ })
+
+ it('returns expected actions for successful action', () => {
+ const store = mockStore(devState)
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'SHOW_PRIVATE_KEY', value: '7ec73b91bb20f209a7ff2d32f542c3420b4fccf14abcc7840d2eff0ebcb18505' },
+ ]
+
+ submitPasswordSpy = sinon.spy(background, 'submitPassword')
+ exportAccountSpy = sinon.spy(background, 'exportAccount')
+
+ return store.dispatch(actions.exportAccount(password, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'))
+ .then((result) => {
+ assert(submitPasswordSpy.calledOnce)
+ assert(exportAccountSpy.calledOnce)
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ it('returns action errors when first func callback errors', () => {
+ const store = mockStore(devState)
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'Incorrect Password.' },
+ ]
+
+ submitPasswordSpy = sinon.stub(background, 'submitPassword')
+ submitPasswordSpy.callsFake((password, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.exportAccount(password, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'))
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ it('returns action errors when second func callback errors', () => {
+ const store = mockStore(devState)
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'Had a problem exporting the account.' },
+ ]
+
+ exportAccountSpy = sinon.stub(background, 'exportAccount')
+ exportAccountSpy.callsFake((address, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.exportAccount(password, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'))
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#setAccountLabel', () => {
+ let setAccountLabelSpy
+
+ beforeEach(() => {
+ setAccountLabelSpy = sinon.stub(background, 'setAccountLabel')
+ })
+
+ it('', () => {
+ const store = mockStore()
+ store.dispatch(actions.setAccountLabel('0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', 'test'))
+ assert(setAccountLabelSpy.calledOnce)
+ })
+ })
+
+ describe('#pairUpdate', () => {
+ beforeEach(() => {
+
+ nock('https://shapeshift.io')
+ .defaultReplyHeaders({ 'access-control-allow-origin': '*' })
+ .get('/marketinfo/btc_eth')
+ .reply(200, {pair: 'BTC_ETH', rate: 25.68289016, minerFee: 0.00176, limit: 0.67748474, minimum: 0.00013569, maxLimit: 0.67758573})
+
+ nock('https://shapeshift.io')
+ .defaultReplyHeaders({ 'access-control-allow-origin': '*' })
+ .get('/coins')
+ .reply(200)
+ })
+
+ afterEach(() => {
+ nock.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+ // issue with dispatch action in callback not showing
+ const expectedActions = [
+ { type: 'SHOW_SUB_LOADING_INDICATION' },
+ { type: 'HIDE_WARNING' },
+ ]
+
+ store.dispatch(actions.pairUpdate('btc'))
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ describe('#setFeatureFlag', () => {
+ let setFeatureFlagSpy
+
+ beforeEach(() => {
+ setFeatureFlagSpy = sinon.stub(background, 'setFeatureFlag')
+ })
+
+ afterEach(() => {
+ setFeatureFlagSpy.restore()
+ })
+
+ it('calls setFeatureFlag in the background', () => {
+ const store = mockStore()
+
+ store.dispatch(actions.setFeatureFlag())
+ assert(setFeatureFlagSpy.calledOnce)
+ })
+
+ it('errors when setFeatureFlag in background throws', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ setFeatureFlagSpy.callsFake((feature, activated, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.setFeatureFlag())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#updateNetworkNonce', () => {
+ let getTransactionCountSpy
+
+ afterEach(() => {
+ getTransactionCountSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+ getTransactionCountSpy = sinon.spy(global.ethQuery, 'getTransactionCount')
+
+ store.dispatch(actions.updateNetworkNonce())
+ .then(() => {
+ assert(getTransactionCountSpy.calledOnce)
+ })
+ })
+
+ it('', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+
+ getTransactionCountSpy = sinon.stub(global.ethQuery, 'getTransactionCount')
+ getTransactionCountSpy.callsFake((address, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.updateNetworkNonce())
+ .catch(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#setUseBlockie', () => {
+ let setUseBlockieSpy
+
+ beforeEach(() => {
+ setUseBlockieSpy = sinon.stub(background, 'setUseBlockie')
+ })
+
+ afterEach(() => {
+ setUseBlockieSpy.restore()
+ })
+
+ it('calls setUseBlockie in background', () => {
+ const store = mockStore()
+
+ store.dispatch(actions.setUseBlockie())
+ assert(setUseBlockieSpy.calledOnce)
+ })
+
+ it('errors when setUseBlockie in background throws', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ { type: 'SET_USE_BLOCKIE', value: undefined },
+ ]
+
+ setUseBlockieSpy.callsFake((val, callback) => {
+ callback(new Error('error'))
+ })
+
+ store.dispatch(actions.setUseBlockie())
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ describe('#updateCurrentLocale', () => {
+ let setCurrentLocaleSpy
+
+ beforeEach(() => {
+ fetchMock.get('*', enLocale)
+ })
+
+ afterEach(() => {
+ setCurrentLocaleSpy.restore()
+ fetchMock.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+ setCurrentLocaleSpy = sinon.spy(background, 'setCurrentLocale')
+
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'SET_CURRENT_LOCALE', value: 'en' },
+ { type: 'SET_LOCALE_MESSAGES', value: enLocale },
+ ]
+
+ return store.dispatch(actions.updateCurrentLocale('en'))
+ .then(() => {
+ assert(setCurrentLocaleSpy.calledOnce)
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+
+ it('', () => {
+ const store = mockStore()
+ const expectedActions = [
+ { type: 'SHOW_LOADING_INDICATION', value: undefined },
+ { type: 'HIDE_LOADING_INDICATION' },
+ { type: 'DISPLAY_WARNING', value: 'error' },
+ ]
+ setCurrentLocaleSpy = sinon.stub(background, 'setCurrentLocale')
+ setCurrentLocaleSpy.callsFake((key, callback) => {
+ callback(new Error('error'))
+ })
+
+ return store.dispatch(actions.updateCurrentLocale('en'))
+ .then(() => {
+ assert.deepEqual(store.getActions(), expectedActions)
+ })
+ })
+ })
+
+ describe('#markPasswordForgotten', () => {
+ let markPasswordForgottenSpy
+
+ beforeEach(() => {
+ markPasswordForgottenSpy = sinon.stub(background, 'markPasswordForgotten')
+ })
+
+ afterEach(() => {
+ markPasswordForgottenSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+ store.dispatch(actions.markPasswordForgotten())
+ assert(markPasswordForgottenSpy.calledOnce)
+ })
+ })
+
+ describe('#unMarkPasswordForgotten', () => {
+ let unMarkPasswordForgottenSpy
+
+ beforeEach(() => {
+ unMarkPasswordForgottenSpy = sinon.stub(background, 'unMarkPasswordForgotten')
+ })
+
+ afterEach(() => {
+ unMarkPasswordForgottenSpy.restore()
+ })
+
+ it('', () => {
+ const store = mockStore()
+ store.dispatch(actions.unMarkPasswordForgotten())
+ assert(unMarkPasswordForgottenSpy.calledOnce)
+ })
+ })
+
+
+})