diff options
Diffstat (limited to 'test/unit/app/controllers')
5 files changed, 356 insertions, 8 deletions
diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js new file mode 100644 index 000000000..4ee73599d --- /dev/null +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -0,0 +1,146 @@ +const assert = require('assert') +const sinon = require('sinon') +const nock = require('nock') +const ObservableStore = require('obs-store') +const DetectTokensController = require('../../../../app/scripts/controllers/detect-tokens') +const NetworkController = require('../../../../app/scripts/controllers/network/network') +const PreferencesController = require('../../../../app/scripts/controllers/preferences') + +describe('DetectTokensController', () => { + + let clock, network, preferences, controller, keyringMemStore + + const sandbox = sinon.createSandbox() + + const noop = () => {} + + const networkControllerProviderConfig = { + getAccounts: noop, + } + + beforeEach(async () => { + + nock('https://api.infura.io') + .get(/.*/) + .reply(200) + + keyringMemStore = new ObservableStore({ isUnlocked: false}) + network = new NetworkController() + preferences = new PreferencesController() + controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) + + network.initializeProvider(networkControllerProviderConfig) + + }) + + after(() => { + sandbox.restore() + nock.cleanAll() + }) + + it('should poll on correct interval', async () => { + const stub = sinon.stub(global, 'setInterval') + new DetectTokensController({ interval: 1337 }) // eslint-disable-line no-new + assert.strictEqual(stub.getCall(0).args[1], 1337) + stub.restore() + }) + + it('should be called on every polling period', async () => { + clock = sandbox.useFakeTimers() + const network = new NetworkController() + network.initializeProvider(networkControllerProviderConfig) + network.setProviderType('mainnet') + const preferences = new PreferencesController() + const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) + controller.isOpen = true + controller.isUnlocked = true + + var stub = sandbox.stub(controller, 'detectNewTokens') + + clock.tick(1) + sandbox.assert.notCalled(stub) + clock.tick(180000) + sandbox.assert.called(stub) + clock.tick(180000) + sandbox.assert.calledTwice(stub) + clock.tick(180000) + sandbox.assert.calledThrice(stub) + }) + + it('should not check tokens while in test network', async () => { + network.setProviderType('rinkeby') + controller.isOpen = true + controller.isUnlocked = true + + var stub = sandbox.stub(controller, 'detectTokenBalance') + .withArgs('0x0D262e5dC4A06a0F1c90cE79C7a60C09DfC884E4').returns(true) + .withArgs('0xBC86727E770de68B1060C91f6BB6945c73e10388').returns(true) + + await controller.detectNewTokens() + sandbox.assert.notCalled(stub) + }) + + it('should only check and add tokens while in main network', async () => { + network.setProviderType('mainnet') + controller.isOpen = true + controller.isUnlocked = true + + sandbox.stub(controller, 'detectTokenBalance') + .withArgs('0x0D262e5dC4A06a0F1c90cE79C7a60C09DfC884E4') + .returns(preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8)) + .withArgs('0xBC86727E770de68B1060C91f6BB6945c73e10388') + .returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18)) + + await controller.detectNewTokens() + assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T'}, + {address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK'}]) + }) + + it('should not detect same token while in main network', async () => { + network.setProviderType('mainnet') + const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore }) + controller.isOpen = true + controller.isUnlocked = true + + sandbox.stub(controller, 'detectTokenBalance') + .withArgs('0x0D262e5dC4A06a0F1c90cE79C7a60C09DfC884E4') + .returns(preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8)) + .withArgs('0xBC86727E770de68B1060C91f6BB6945c73e10388') + .returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18)) + + await controller.detectNewTokens() + assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T'}, + {address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK'}]) + }) + + it('should trigger detect new tokens when change address', async () => { + network.setProviderType('mainnet') + controller.isOpen = true + controller.isUnlocked = true + var stub = sandbox.stub(controller, 'detectNewTokens') + await preferences.setSelectedAddress('0xbc86727e770de68b1060c91f6bb6945c73e10388') + sandbox.assert.called(stub) + }) + + it('should trigger detect new tokens when submit password', async () => { + network.setProviderType('mainnet') + controller.isOpen = true + controller.selectedAddress = '0x0' + var stub = sandbox.stub(controller, 'detectNewTokens') + await controller._keyringMemStore.updateState({ isUnlocked: true }) + sandbox.assert.called(stub) + }) + + it('should not trigger detect new tokens when not open or not unlocked', async () => { + network.setProviderType('mainnet') + controller.isOpen = true + controller.isUnlocked = false + var stub = sandbox.stub(controller, 'detectTokenBalance') + clock.tick(180000) + sandbox.assert.notCalled(stub) + controller.isOpen = false + controller.isUnlocked = true + clock.tick(180000) + sandbox.assert.notCalled(stub) + }) +}) diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index cbd949e69..471321b9b 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -5,7 +5,7 @@ const nock = require('nock') const createThoughStream = require('through2').obj const blacklistJSON = require('eth-phishing-detect/src/config') const MetaMaskController = require('../../../../app/scripts/metamask-controller') -const firstTimeState = require('../../../../app/scripts/first-time-state') +const firstTimeState = require('../../../unit/localhostState') const createTxMeta = require('../../../lib/createTxMeta') const currentNetworkId = 42 @@ -224,6 +224,129 @@ describe('MetaMaskController', function () { }) }) + describe('connectHardware', function () { + + it('should throw if it receives an unknown device name', async function () { + try { + await metamaskController.connectHardware('Some random device name', 0) + } catch (e) { + assert.equal(e, 'Error: MetamaskController:connectHardware - Unknown device') + } + }) + + it('should add the Trezor Hardware keyring', async function () { + sinon.spy(metamaskController.keyringController, 'addNewKeyring') + await metamaskController.connectHardware('trezor', 0).catch((e) => null) + const keyrings = await metamaskController.keyringController.getKeyringsByType( + 'Trezor Hardware' + ) + assert.equal(metamaskController.keyringController.addNewKeyring.getCall(0).args, 'Trezor Hardware') + assert.equal(keyrings.length, 1) + }) + + }) + + describe('checkHardwareStatus', function () { + it('should throw if it receives an unknown device name', async function () { + try { + await metamaskController.checkHardwareStatus('Some random device name') + } catch (e) { + assert.equal(e, 'Error: MetamaskController:checkHardwareStatus - Unknown device') + } + }) + + it('should be locked by default', async function () { + await metamaskController.connectHardware('trezor', 0).catch((e) => null) + const status = await metamaskController.checkHardwareStatus('trezor') + assert.equal(status, false) + }) + }) + + describe('forgetDevice', function () { + it('should throw if it receives an unknown device name', async function () { + try { + await metamaskController.forgetDevice('Some random device name') + } catch (e) { + assert.equal(e, 'Error: MetamaskController:forgetDevice - Unknown device') + } + }) + + it('should wipe all the keyring info', async function () { + await metamaskController.connectHardware('trezor', 0).catch((e) => null) + await metamaskController.forgetDevice('trezor') + const keyrings = await metamaskController.keyringController.getKeyringsByType( + 'Trezor Hardware' + ) + + assert.deepEqual(keyrings[0].accounts, []) + assert.deepEqual(keyrings[0].page, 0) + assert.deepEqual(keyrings[0].isUnlocked(), false) + }) + }) + + describe('unlockTrezorAccount', function () { + let accountToUnlock + let windowOpenStub + let addNewAccountStub + let getAccountsStub + beforeEach(async function () { + accountToUnlock = 10 + windowOpenStub = sinon.stub(window, 'open') + windowOpenStub.returns(noop) + + addNewAccountStub = sinon.stub(metamaskController.keyringController, 'addNewAccount') + addNewAccountStub.returns({}) + + getAccountsStub = sinon.stub(metamaskController.keyringController, 'getAccounts') + // Need to return different address to mock the behavior of + // adding a new account from the keyring + getAccountsStub.onCall(0).returns(Promise.resolve(['0x1'])) + getAccountsStub.onCall(1).returns(Promise.resolve(['0x2'])) + getAccountsStub.onCall(2).returns(Promise.resolve(['0x3'])) + getAccountsStub.onCall(3).returns(Promise.resolve(['0x4'])) + sinon.spy(metamaskController.preferencesController, 'setAddresses') + sinon.spy(metamaskController.preferencesController, 'setSelectedAddress') + sinon.spy(metamaskController.preferencesController, 'setAccountLabel') + await metamaskController.connectHardware('trezor', 0).catch((e) => null) + await metamaskController.unlockTrezorAccount(accountToUnlock).catch((e) => null) + }) + + afterEach(function () { + metamaskController.keyringController.addNewAccount.restore() + window.open.restore() + }) + + it('should set accountToUnlock in the keyring', async function () { + const keyrings = await metamaskController.keyringController.getKeyringsByType( + 'Trezor Hardware' + ) + assert.equal(keyrings[0].unlockedAccount, accountToUnlock) + }) + + + it('should call keyringController.addNewAccount', async function () { + assert(metamaskController.keyringController.addNewAccount.calledOnce) + }) + + it('should call keyringController.getAccounts ', async function () { + assert(metamaskController.keyringController.getAccounts.called) + }) + + it('should call preferencesController.setAddresses', async function () { + assert(metamaskController.preferencesController.setAddresses.calledOnce) + }) + + it('should call preferencesController.setSelectedAddress', async function () { + assert(metamaskController.preferencesController.setSelectedAddress.calledOnce) + }) + + it('should call preferencesController.setAccountLabel', async function () { + assert(metamaskController.preferencesController.setAccountLabel.calledOnce) + }) + + + }) + describe('#setCustomRpc', function () { let rpcTarget @@ -355,6 +478,39 @@ describe('MetaMaskController', function () { }) }) + describe('#removeAccount', function () { + let ret + const addressToRemove = '0x1' + + beforeEach(async function () { + sinon.stub(metamaskController.preferencesController, 'removeAddress') + sinon.stub(metamaskController.accountTracker, 'removeAccount') + sinon.stub(metamaskController.keyringController, 'removeAccount') + + ret = await metamaskController.removeAccount(addressToRemove) + + }) + + afterEach(function () { + metamaskController.keyringController.removeAccount.restore() + metamaskController.accountTracker.removeAccount.restore() + metamaskController.preferencesController.removeAddress.restore() + }) + + it('should call preferencesController.removeAddress', async function () { + assert(metamaskController.preferencesController.removeAddress.calledWith(addressToRemove)) + }) + it('should call accountTracker.removeAccount', async function () { + assert(metamaskController.accountTracker.removeAccount.calledWith(addressToRemove)) + }) + it('should call keyringController.removeAccount', async function () { + assert(metamaskController.keyringController.removeAccount.calledWith(addressToRemove)) + }) + it('should return address', async function () { + assert.equal(ret, '0x1') + }) + }) + describe('#clearSeedWordCache', function () { it('should have set seed words', function () { diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index e5e751b57..e055500b1 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -52,6 +52,31 @@ describe('preferences controller', function () { }) }) + describe('removeAddress', function () { + it('should remove an address from state', function () { + preferencesController.setAddresses([ + '0xda22le', + '0x7e57e2', + ]) + + preferencesController.removeAddress('0xda22le') + + assert.equal(preferencesController.store.getState().identities['0xda22le'], undefined) + }) + + it('should switch accounts if the selected address is removed', function () { + preferencesController.setAddresses([ + '0xda22le', + '0x7e57e2', + ]) + + preferencesController.setSelectedAddress('0x7e57e2') + preferencesController.removeAddress('0x7e57e2') + + assert.equal(preferencesController.getSelectedAddress(), '0xda22le') + }) + }) + describe('setAccountLabel', function () { it('should update a label for the given account', function () { preferencesController.setAddresses([ diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index 7eb111cfb..5ac813b49 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -354,9 +354,16 @@ describe('Transaction Controller', function () { ]) }) - it('should set the transaction to rejected from unapproved', async function () { - await txController.cancelTransaction(0) - assert.equal(txController.txStateManager.getTx(0).status, 'rejected') + it('should emit a status change to rejected', function (done) { + txController.once('tx:status-update', (txId, status) => { + try { + assert.equal(status, 'rejected', 'status should e rejected') + assert.equal(txId, 0, 'id should e 0') + done() + } catch (e) { done(e) } + }) + + txController.cancelTransaction(0) }) }) @@ -375,8 +382,9 @@ describe('Transaction Controller', function () { }) it('should publish a tx, updates the rawTx when provided a one', async function () { + const rawTx = '0x477b2e6553c917af0db0388ae3da62965ff1a184558f61b749d1266b2e6d024c' txController.txStateManager.addTx(txMeta) - await txController.publishTransaction(txMeta.id) + await txController.publishTransaction(txMeta.id, rawTx) const publishedTx = txController.txStateManager.getTx(1) assert.equal(publishedTx.hash, hash) assert.equal(publishedTx.status, 'submitted') diff --git a/test/unit/app/controllers/transactions/tx-state-manager-test.js b/test/unit/app/controllers/transactions/tx-state-manager-test.js index 2f91b1545..88bdaa60e 100644 --- a/test/unit/app/controllers/transactions/tx-state-manager-test.js +++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js @@ -43,14 +43,13 @@ describe('TransactionStateManager', function () { }) describe('#setTxStatusRejected', function () { - it('sets the tx status to rejected', function () { + it('sets the tx status to rejected and removes it from history', function () { const tx = { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {} } txStateManager.addTx(tx) txStateManager.setTxStatusRejected(1) const result = txStateManager.getTxList() assert.ok(Array.isArray(result)) - assert.equal(result.length, 1) - assert.equal(result[0].status, 'rejected') + assert.equal(result.length, 0) }) it('should emit a rejected event to signal the exciton of callback', (done) => { @@ -287,4 +286,18 @@ describe('TransactionStateManager', function () { }) }) + + describe('#_removeTx', function () { + it('should remove the transaction from the storage', () => { + txStateManager._saveTxList([ {id: 1} ]) + txStateManager._removeTx(1) + assert(!txStateManager.getFullTxList().length, 'txList should be empty') + }) + + it('should only remove the transaction with ID 1 from the storage', () => { + txStateManager._saveTxList([ {id: 1}, {id: 2} ]) + txStateManager._removeTx(1) + assert.equal(txStateManager.getFullTxList()[0].id, 2, 'txList should have a id of 2') + }) + }) }) |