diff options
Diffstat (limited to 'test/unit/ui')
-rw-r--r-- | test/unit/ui/add-token.spec.js | 2 | ||||
-rw-r--r-- | test/unit/ui/app/actions.spec.js | 1468 | ||||
-rw-r--r-- | test/unit/ui/app/components/identicon.spec.js | 36 | ||||
-rw-r--r-- | test/unit/ui/app/components/token-cell.spec.js | 69 | ||||
-rw-r--r-- | test/unit/ui/app/selectors.spec.js | 175 | ||||
-rw-r--r-- | test/unit/ui/etherscan-prefix-for-network.spec.js | 26 |
6 files changed, 1775 insertions, 1 deletions
diff --git a/test/unit/ui/add-token.spec.js b/test/unit/ui/add-token.spec.js index 69b7fb620..f6b6155a0 100644 --- a/test/unit/ui/add-token.spec.js +++ b/test/unit/ui/add-token.spec.js @@ -1,7 +1,7 @@ const assert = require('assert') const { createMockStore } = require('redux-test-utils') const h = require('react-hyperscript') -const { shallowWithStore } = require('../../lib/shallow-with-store') +const { shallowWithStore } = require('../../lib/render-helpers') const AddTokenScreen = require('../../../old-ui/app/add-token') describe('Add Token Screen', function () { 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) + }) + }) + + +}) diff --git a/test/unit/ui/app/components/identicon.spec.js b/test/unit/ui/app/components/identicon.spec.js new file mode 100644 index 000000000..a2f8d8246 --- /dev/null +++ b/test/unit/ui/app/components/identicon.spec.js @@ -0,0 +1,36 @@ +import React from 'react' +import assert from 'assert' +import thunk from 'redux-thunk' +import configureMockStore from 'redux-mock-store' +import { mount } from 'enzyme' + +import IdenticonComponent from '../../../../../ui/app/components/identicon' + +describe('Identicon Component', () => { + + const state = { + metamask: { + useBlockie: false, + }, + } + + const middlewares = [thunk] + const mockStore = configureMockStore(middlewares) + const store = mockStore(state) + + it('renders default eth_logo identicon with no props', () => { + const wrapper = mount(<IdenticonComponent store={store}/>) + assert.equal(wrapper.find('img.balance-icon').prop('src'), './images/eth_logo.svg') + }) + + it('renders custom image and add className props', () => { + const wrapper = mount(<IdenticonComponent store={store} className={'test-image'} image={'test-image'} />) + assert.equal(wrapper.find('img.test-image').prop('className'), 'test-image identicon') + assert.equal(wrapper.find('img.test-image').prop('src'), 'test-image') + }) + + it('renders div with address prop', () => { + const wrapper = mount(<IdenticonComponent store={store} className={'test-address'} address={'0xTest'} />) + assert.equal(wrapper.find('div.test-address').prop('className'), 'test-address identicon') + }) +}) diff --git a/test/unit/ui/app/components/token-cell.spec.js b/test/unit/ui/app/components/token-cell.spec.js new file mode 100644 index 000000000..6145c6924 --- /dev/null +++ b/test/unit/ui/app/components/token-cell.spec.js @@ -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 '../../../../../ui/app/components/token-cell' +import Identicon from '../../../../../ui/app/components/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') + }) + +}) diff --git a/test/unit/ui/app/selectors.spec.js b/test/unit/ui/app/selectors.spec.js new file mode 100644 index 000000000..78c4267ee --- /dev/null +++ b/test/unit/ui/app/selectors.spec.js @@ -0,0 +1,175 @@ +const assert = require('assert') +const selectors = require('../../../../ui/app/selectors') +const mockState = require('../../../data/mock-state.json') +const Eth = require('ethjs') + +const { createTestProviderTools } = require('../../../stub/provider') +const provider = createTestProviderTools({ scaffold: {}}).provider + +describe('Selectors', function () { + + describe('#getSelectedAddress', function () { + let state + beforeEach(function () { + state = { + metamask: { + accounts: { + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { + 'balance': '0x0', + 'address': '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + }, + }, + }, + } + }) + + it('returns first account if selectedAddress is undefined', function () { + assert.equal(selectors.getSelectedAddress(state), '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') + }) + + it('returns selectedAddress', function () { + assert.equal(selectors.getSelectedAddress(mockState), '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') + }) + + }) + + it('returns selected identity', function () { + const identity = selectors.getSelectedIdentity(mockState) + assert.equal(identity.address, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') + assert.equal(identity.name, 'Test Account') + }) + + it('returns selected account', function () { + const account = selectors.getSelectedAccount(mockState) + assert.equal(account.balance, '0x0') + assert.equal(account.address, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') + }) + + it('returns selected token from first token list', function () { + const token = selectors.getSelectedToken(mockState) + assert.equal(token.address, '0x108cf70c7d384c552f42c07c41c0e1e46d77ea0d') + assert.equal(token.symbol, 'TEST') + assert.equal(token.decimals, '0') + }) + + describe('#getSelectedTokenExchangeRate', function () { + it('returns token exchange rate for first token', function () { + const tokenRate = selectors.getSelectedTokenExchangeRate(mockState) + assert.equal(tokenRate, '0.00039345803819379796') + }) + }) + + + describe('#getTokenExchangeRate', function () { + let missingTokenRate + + beforeEach(function () { + missingTokenRate = { + metamask: { + 'contractExchangeRates': {}, + }, + } + }) + + it('returns 0 token exchange rate for a token not in state', function () { + const tokenRate = selectors.getTokenExchangeRate(missingTokenRate, '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5') + assert.equal(tokenRate, 0) + }) + + it('returns token exchange rate for specified token in state', function () { + const tokenRate = selectors.getTokenExchangeRate(mockState, '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5') + assert.equal(tokenRate, 0.00008189274407698049) + }) + + }) + + it('returns conversionRate from state', function () { + assert.equal(selectors.conversionRateSelector(mockState), 556.12) + }) + + it('returns address book from state', function () { + const addressBook = selectors.getAddressBook(mockState) + assert.equal(addressBook[0].address, '0xc42edfcc21ed14dda456aa0756c153f7985d8813') + assert.equal(addressBook[0].name, '') + }) + + it('returns accounts with balance, address, and name from identity and accounts in state', function () { + const accountsWithSendEther = selectors.accountsWithSendEtherInfoSelector(mockState) + assert.equal(accountsWithSendEther.length, 2) + assert.equal(accountsWithSendEther[0].balance, '0x0') + assert.equal(accountsWithSendEther[0].address, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') + assert.equal(accountsWithSendEther[0].name, 'Test Account') + }) + + it('returns selected account with balance, address, and name from accountsWithSendEtherInfoSelector', function () { + const currentAccountwithSendEther = selectors.getCurrentAccountWithSendEtherInfo(mockState) + assert.equal(currentAccountwithSendEther.balance, '0x0') + assert.equal(currentAccountwithSendEther.address, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') + assert.equal(currentAccountwithSendEther.name, 'Test Account') + }) + + describe('#transactionSelector', function () { + it('returns transactions from state', function () { + selectors.transactionsSelector(mockState) + }) + }) + + it('#getGasIsLoading', () => { + const gasIsLoading = selectors.getGasIsLoading(mockState) + assert.equal(gasIsLoading, false) + }) + + describe('Send From', () => { + it('#getSendFrom', () => { + const sendFrom = selectors.getSendFrom(mockState) + assert.equal(sendFrom, '0xc42edfcc21ed14dda456aa0756c153f7985d8813') + }) + + it('#getForceGasMin', () => { + const forceGasMin = selectors.getForceGasMin(mockState) + assert.equal(forceGasMin, null) + }) + + it('#getSendAmount', () => { + const sendAmount = selectors.getSendAmount(mockState) + assert.equal(sendAmount, '1bc16d674ec80000') + }) + + it('#getSendMaxModeState', () => { + const sendMaxModeState = selectors.getSendMaxModeState(mockState) + assert.equal(sendMaxModeState, false) + }) + }) + + it('#getCurrentCurrency', () => { + const currentCurrency = selectors.getCurrentCurrency(mockState) + assert.equal(currentCurrency, 'usd') + }) + + it('#getSelectedTokenToFiatRate', () => { + const selectedTokenToFiatRate = selectors.getSelectedTokenToFiatRate(mockState) + assert.equal(selectedTokenToFiatRate, '0.21880988420033493') + }) + + describe('#getSelectedTokenContract', () => { + + beforeEach(() => { + global.eth = new Eth(provider) + }) + + it('', () => { + const selectedTokenContract = selectors.getSelectedTokenContract(mockState) + assert(selectedTokenContract.abi) + }) + }) + + it('#getCurrentViewContext', () => { + const currentViewContext = selectors.getCurrentViewContext(mockState) + assert.equal(currentViewContext, '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc') + }) + + it('#getTotalUnapprovedCount', () => { + const totalUnapprovedCount = selectors.getTotalUnapprovedCount(mockState) + assert.equal(totalUnapprovedCount, 1) + }) +}) diff --git a/test/unit/ui/etherscan-prefix-for-network.spec.js b/test/unit/ui/etherscan-prefix-for-network.spec.js new file mode 100644 index 000000000..f0aeb8306 --- /dev/null +++ b/test/unit/ui/etherscan-prefix-for-network.spec.js @@ -0,0 +1,26 @@ +const assert = require('assert') +const etherscanNetworkPrefix = require('../../../ui/lib/etherscan-prefix-for-network') + +describe('Etherscan Network Prefix', () => { + + it('returns empy string as default value', () => { + assert.equal(etherscanNetworkPrefix(), '') + }) + + it('returns empty string as a prefix for networkId of 1', () => { + assert.equal(etherscanNetworkPrefix(1), '') + }) + + it('returns ropsten as prefix for networkId of 3', () => { + assert.equal(etherscanNetworkPrefix(3), 'ropsten.') + }) + + it('returns rinkeby as prefix for networkId of 4', () => { + assert.equal(etherscanNetworkPrefix(4), 'rinkeby.') + }) + + it('returs kovan as prefix for networkId of 42', () => { + assert.equal(etherscanNetworkPrefix(42), 'kovan.') + }) + +}) |