diff options
author | Thomas <thomas.b.huang@gmail.com> | 2018-10-31 20:55:25 +0800 |
---|---|---|
committer | Thomas <thomas.b.huang@gmail.com> | 2018-10-31 20:55:25 +0800 |
commit | 7531de14f9575e59b9d0a1b30cf0df46dbc4af67 (patch) | |
tree | d9268e89a9fd7e5c6bf3c7c82c195422d7ffa117 /test | |
parent | 611a61b7bc576bb83a6b7851f26d00488fe060f2 (diff) | |
parent | ac079365e6b4cf8b19db127e6971fa694fa54fff (diff) | |
download | tangerine-wallet-browser-7531de14f9575e59b9d0a1b30cf0df46dbc4af67.tar tangerine-wallet-browser-7531de14f9575e59b9d0a1b30cf0df46dbc4af67.tar.gz tangerine-wallet-browser-7531de14f9575e59b9d0a1b30cf0df46dbc4af67.tar.bz2 tangerine-wallet-browser-7531de14f9575e59b9d0a1b30cf0df46dbc4af67.tar.lz tangerine-wallet-browser-7531de14f9575e59b9d0a1b30cf0df46dbc4af67.tar.xz tangerine-wallet-browser-7531de14f9575e59b9d0a1b30cf0df46dbc4af67.tar.zst tangerine-wallet-browser-7531de14f9575e59b9d0a1b30cf0df46dbc4af67.zip |
Merge branch 'develop' into reducers
Diffstat (limited to 'test')
-rw-r--r-- | test/data/2-state.json | 70 | ||||
-rw-r--r-- | test/data/mock-state.json | 4 | ||||
-rw-r--r-- | test/e2e/beta/from-import-beta-ui.spec.js | 4 | ||||
-rw-r--r-- | test/e2e/beta/metamask-beta-ui.spec.js | 44 | ||||
-rwxr-xr-x | test/e2e/beta/run-drizzle.sh | 2 | ||||
-rw-r--r-- | test/integration/lib/add-token.js | 140 | ||||
-rw-r--r-- | test/integration/lib/currency-localization.js | 2 | ||||
-rw-r--r-- | test/integration/lib/send-new-ui.js | 22 | ||||
-rw-r--r-- | test/unit/app/controllers/network-contoller-test.js | 2 | ||||
-rw-r--r-- | test/unit/app/controllers/preferences-controller-test.js | 24 | ||||
-rw-r--r-- | test/unit/app/controllers/transactions/tx-controller-test.js | 30 | ||||
-rw-r--r-- | test/unit/components/balance-component-test.js | 44 | ||||
-rw-r--r-- | test/unit/ui/app/actions.spec.js | 1468 | ||||
-rw-r--r-- | test/unit/ui/app/components/identicon.spec.js | 36 |
14 files changed, 1629 insertions, 263 deletions
diff --git a/test/data/2-state.json b/test/data/2-state.json new file mode 100644 index 000000000..d41a403ff --- /dev/null +++ b/test/data/2-state.json @@ -0,0 +1,70 @@ +{ "isInitialized": true, + "provider": { "type": "rpc", "rpcTarget": "http://localhost:8545" }, + "network": "loading", + "accounts": { + "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc": { + "address": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", + "balance": "0x0" + }, + "0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b": { + "address": "0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b", + "balance": "0x0" + } + }, + "currentBlockGasLimit": "", + "unapprovedTxs": {}, + "selectedAddressTxList": [], + "computedBalances": {}, + "unapprovedMsgs": {}, + "unapprovedMsgCount": 0, + "unapprovedPersonalMsgs": {}, + "unapprovedPersonalMsgCount": 0, + "unapprovedTypedMessages": {}, + "unapprovedTypedMessagesCount": 0, + "isUnlocked": true, + "keyringTypes": [ "Simple Key Pair", "HD Key Tree" ], + "keyrings":[ + { "type": "HD Key Tree", + "accounts": [ + "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc" + ] + }, + { + "type": "Simple Key Pair", + "accounts": [ + "0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b" + ] + } + ], + "frequentRpcList": [], + "currentAccountTab": "history", + "tokens": [], + "useBlockie": false, + "featureFlags": {}, + "currentLocale": null, + "identities": { + "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc": { + "name": "Account 1", + "address": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc" + }, + "0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b": { + "name": "Account 2", + "address": "0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b" + } + }, + + "lostIdentities": {}, + "selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", + "recentBlocks": [], + "addressBook": [], + "currentCurrency": "usd", + "conversionRate": 288.45, + "conversionDate": 1506444677, + "nextUnreadNotice": null, + "noActiveNotices": true, + "shapeShiftTxList": [], + "infuraNetworkStatus": {}, + "lostAccounts": [], + "seedWords": "debris dizzy just program just float decrease vacant alarm reduce speak stadium", + "forgottenPassword": null +}
\ No newline at end of file diff --git a/test/data/mock-state.json b/test/data/mock-state.json index 7e083c60e..8deff5531 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -111,7 +111,9 @@ "0x108cf70c7d384c552f42c07c41c0e1e46d77ea0d": 0.00039345803819379796, "0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5": 0.00008189274407698049 }, + "ticker": "ETH", "currentCurrency": "usd", + "nativeCurrency": "ETH", "conversionRate": 556.12, "addressBook": [ { @@ -1248,4 +1250,4 @@ "context": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc" } } -}
\ No newline at end of file +} diff --git a/test/e2e/beta/from-import-beta-ui.spec.js b/test/e2e/beta/from-import-beta-ui.spec.js index 32aaa29a6..d2c3f8958 100644 --- a/test/e2e/beta/from-import-beta-ui.spec.js +++ b/test/e2e/beta/from-import-beta-ui.spec.js @@ -286,7 +286,7 @@ describe('Using MetaMask with an existing account', function () { await delay(regularDelayMs) const inputAddress = await findElement(driver, By.css('input[placeholder="Recipient Address"]')) - const inputAmount = await findElement(driver, By.css('.currency-display__input')) + const inputAmount = await findElement(driver, By.css('.unit-input__input')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') await inputAmount.sendKeys('1') @@ -319,7 +319,7 @@ describe('Using MetaMask with an existing account', function () { const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) assert.equal(txValues.length, 1) - assert.equal(await txValues[0].getText(), '-1 ETH') + assert.ok(/-1\s*ETH/.test(await txValues[0].getText())) }) }) diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index 8d1ecac0d..eaa7d18cd 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-ui.spec.js @@ -371,7 +371,7 @@ describe('MetaMask', function () { it('balance renders', async () => { const balance = await findElement(driver, By.css('.balance-display .token-amount')) - await driver.wait(until.elementTextMatches(balance, /100.+ETH/)) + await driver.wait(until.elementTextMatches(balance, /100\s*ETH/)) await delay(regularDelayMs) }) }) @@ -383,7 +383,7 @@ describe('MetaMask', function () { await delay(regularDelayMs) const inputAddress = await findElement(driver, By.css('input[placeholder="Recipient Address"]')) - const inputAmount = await findElement(driver, By.css('.currency-display__input')) + const inputAmount = await findElement(driver, By.css('.unit-input__input')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') await inputAmount.sendKeys('1') @@ -420,7 +420,7 @@ describe('MetaMask', function () { if (process.env.SELENIUM_BROWSER !== 'firefox') { const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txValues, /-1\sETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-1\s*ETH/), 10000) } }) }) @@ -462,7 +462,7 @@ describe('MetaMask', function () { assert.equal(transactions.length, 2) const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txValues, /-3\sETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-3\s*ETH/), 10000) }) }) @@ -540,7 +540,7 @@ describe('MetaMask', function () { await findElements(driver, By.css('.transaction-list-item')) const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txListValue, /-4\sETH/), 10000) + await driver.wait(until.elementTextMatches(txListValue, /-4\s*ETH/), 10000) await txListValue.click() await delay(regularDelayMs) @@ -574,7 +574,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txValues[0], /-4\sETH/), 10000) + await driver.wait(until.elementTextMatches(txValues[0], /-4\s*ETH/), 10000) // const txAccounts = await findElements(driver, By.css('.tx-list-account')) // const firstTxAddress = await txAccounts[0].getText() @@ -606,7 +606,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await findElement(driver, By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txValues, /-0\sETH/), 10000) + await driver.wait(until.elementTextMatches(txValues, /-0\s*ETH/), 10000) await closeAllWindowHandlesExcept(driver, [extension, dapp]) await driver.switchTo().window(extension) @@ -616,9 +616,9 @@ describe('MetaMask', function () { const balance = await findElement(driver, By.css('.transaction-view-balance__primary-balance')) await delay(regularDelayMs) if (process.env.SELENIUM_BROWSER !== 'firefox') { - await driver.wait(until.elementTextMatches(balance, /^92.*ETH.*$/), 10000) + await driver.wait(until.elementTextMatches(balance, /^92.*\s*ETH.*$/), 10000) const tokenAmount = await balance.getText() - assert.ok(/^92.*ETH.*$/.test(tokenAmount)) + assert.ok(/^92.*\s*ETH.*$/.test(tokenAmount)) await delay(regularDelayMs) } }) @@ -662,7 +662,7 @@ describe('MetaMask', function () { }) it('clicks on the Add Token button', async () => { - const addToken = await driver.findElement(By.css('.wallet-view__add-token-button')) + const addToken = await driver.findElement(By.xpath(`//div[contains(text(), 'Add Token')]`)) await addToken.click() await delay(regularDelayMs) }) @@ -702,7 +702,7 @@ describe('MetaMask', function () { await delay(regularDelayMs) const inputAddress = await findElement(driver, By.css('input[placeholder="Recipient Address"]')) - const inputAmount = await findElement(driver, By.css('.currency-display__input')) + const inputAmount = await findElement(driver, By.css('.unit-input__input')) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') await inputAmount.sendKeys('50') @@ -764,7 +764,7 @@ describe('MetaMask', function () { // test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved, // or possibly until we use latest version of firefox in the tests if (process.env.SELENIUM_BROWSER !== 'firefox') { - await driver.wait(until.elementTextMatches(txValues[0], /-50\sTST/), 10000) + await driver.wait(until.elementTextMatches(txValues[0], /-50\s*TST/), 10000) } driver.wait(async () => { @@ -798,7 +798,7 @@ describe('MetaMask', function () { await findElements(driver, By.css('.transaction-list__pending-transactions')) const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txListValue, /-7\sTST/), 10000) + await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/), 10000) await txListValue.click() await delay(regularDelayMs) @@ -834,8 +834,8 @@ describe('MetaMask', function () { await save.click() await driver.wait(until.stalenessOf(gasModal)) - const gasFeeInputs = await findElements(driver, By.css('.confirm-detail-row__eth')) - assert.equal(await gasFeeInputs[0].getText(), '♦ 0.0006') + const gasFeeInputs = await findElements(driver, By.css('.confirm-detail-row__primary')) + assert.equal(await gasFeeInputs[0].getText(), '0.0006') }) it('submits the transaction', async function () { @@ -851,7 +851,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txValues[0], /-7\sTST/)) + await driver.wait(until.elementTextMatches(txValues[0], /-7\s*TST/)) const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) await driver.wait(until.elementTextMatches(txStatuses[0], /Sent\sToken/)) @@ -897,7 +897,7 @@ describe('MetaMask', function () { const [txListItem] = await findElements(driver, By.css('.transaction-list-item')) const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txListValue, /-7\sTST/)) + await driver.wait(until.elementTextMatches(txListValue, /-7\s*TST/)) await txListItem.click() await delay(regularDelayMs) }) @@ -957,8 +957,8 @@ describe('MetaMask', function () { await save.click() await driver.wait(until.stalenessOf(gasModal)) - const gasFeeInputs = await findElements(driver, By.css('.confirm-detail-row__eth')) - assert.equal(await gasFeeInputs[0].getText(), '♦ 0.0006') + const gasFeeInputs = await findElements(driver, By.css('.confirm-detail-row__primary')) + assert.equal(await gasFeeInputs[0].getText(), '0.0006') }) it('submits the transaction', async function () { @@ -974,7 +974,7 @@ describe('MetaMask', function () { }, 10000) const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) - await driver.wait(until.elementTextMatches(txValues[0], /-7\sTST/)) + await driver.wait(until.elementTextMatches(txValues[0], /-7\s*TST/)) const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) await driver.wait(until.elementTextMatches(txStatuses[0], /Approve/)) }) @@ -1002,7 +1002,7 @@ describe('MetaMask', function () { describe('Add existing token using search', () => { it('clicks on the Add Token button', async () => { - const addToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Token')]`)) + const addToken = await findElement(driver, By.xpath(`//div[contains(text(), 'Add Token')]`)) await addToken.click() await delay(regularDelayMs) }) @@ -1027,7 +1027,7 @@ describe('MetaMask', function () { it('renders the balance for the chosen token', async () => { const balance = await findElement(driver, By.css('.transaction-view-balance__token-balance')) - await driver.wait(until.elementTextMatches(balance, /0\sBAT/)) + await driver.wait(until.elementTextMatches(balance, /0\s*BAT/)) await delay(regularDelayMs) }) }) diff --git a/test/e2e/beta/run-drizzle.sh b/test/e2e/beta/run-drizzle.sh index 7bfffd7e6..bfb7e6fdb 100755 --- a/test/e2e/beta/run-drizzle.sh +++ b/test/e2e/beta/run-drizzle.sh @@ -11,7 +11,7 @@ sleep 5 cd test/e2e/beta/ rm -rf drizzle-test mkdir drizzle-test && cd drizzle-test -npm install truffle +sudo npm install -g truffle truffle unbox drizzle echo "Deploying contracts for Drizzle test..." truffle compile && truffle migrate diff --git a/test/integration/lib/add-token.js b/test/integration/lib/add-token.js deleted file mode 100644 index bb9d0d10f..000000000 --- a/test/integration/lib/add-token.js +++ /dev/null @@ -1,140 +0,0 @@ -const reactTriggerChange = require('react-trigger-change') -const { - timeout, - queryAsync, - findAsync, -} = require('../../lib/util') - -QUnit.module('Add token flow') - -QUnit.test('successful add token flow', (assert) => { - const done = assert.async() - runAddTokenFlowTest(assert) - .then(done) - .catch(err => { - assert.notOk(err, `Error was thrown: ${err.stack}`) - done() - }) -}) - -async function runAddTokenFlowTest (assert, done) { - const selectState = await queryAsync($, 'select') - selectState.val('add token') - reactTriggerChange(selectState[0]) - - // Used to set values on TextField input component - const nativeInputValueSetter = Object.getOwnPropertyDescriptor( - window.HTMLInputElement.prototype, 'value' - ).set - - // Check that no tokens have been added - assert.ok($('.token-list-item').length === 0, 'no tokens added') - - // Go to Add Token screen - let addTokenButton = await queryAsync($, 'button.btn-primary.wallet-view__add-token-button') - assert.ok(addTokenButton[0], 'add token button present') - addTokenButton[0].click() - - // Verify Add Token screen - let addTokenWrapper = await queryAsync($, '.page-container') - assert.ok(addTokenWrapper[0], 'add token wrapper renders') - - let addTokenTitle = await queryAsync($, '.page-container__title') - assert.equal(addTokenTitle[0].textContent, 'Add Tokens', 'add token title is correct') - - // Cancel Add Token - const cancelAddTokenButton = await queryAsync($, 'button.btn-default.btn--large.page-container__footer-button') - assert.ok(cancelAddTokenButton[0], 'cancel add token button present') - cancelAddTokenButton.click() - - assert.ok($('.wallet-view')[0], 'cancelled and returned to account detail wallet view') - - // Return to Add Token Screen - addTokenButton = await queryAsync($, 'button.btn-primary.wallet-view__add-token-button') - assert.ok(addTokenButton[0], 'add token button present') - addTokenButton[0].click() - - // Verify Add Token Screen - addTokenWrapper = await queryAsync($, '.page-container') - addTokenTitle = await queryAsync($, '.page-container__title') - assert.ok(addTokenWrapper[0], 'add token wrapper renders') - assert.equal(addTokenTitle[0].textContent, 'Add Tokens', 'add token title is correct') - - // Search for token - const searchInput = (await findAsync(addTokenWrapper, '#search-tokens'))[0] - searchInput.focus() - await timeout(1000) - nativeInputValueSetter.call(searchInput, 'a') - searchInput.dispatchEvent(new Event('input', { bubbles: true})) - - // Click token to add - const tokenWrapper = await queryAsync($, 'div.token-list__token') - assert.ok(tokenWrapper[0], 'token found') - const tokenImageProp = tokenWrapper.find('.token-list__token-icon').css('background-image') - const tokenImageUrl = tokenImageProp.slice(5, -2) - tokenWrapper[0].click() - - // Click Next button - const nextButton = await queryAsync($, 'button.btn-primary.btn--large') - assert.equal(nextButton[0].textContent, 'Next', 'next button rendered') - nextButton[0].click() - - // Confirm Add token - const confirmAddToken = await queryAsync($, '.confirm-add-token') - assert.ok(confirmAddToken[0], 'confirm add token rendered') - assert.ok($('button.btn-primary.btn--large')[0], 'confirm add token button found') - $('button.btn-primary.btn--large')[0].click() - - // Verify added token image - let heroBalance = await queryAsync($, '.transaction-view-balance__balance-container') - assert.ok(heroBalance, 'rendered hero balance') - assert.ok(tokenImageUrl.indexOf(heroBalance.find('img').attr('src')) > -1, 'token added') - - // Return to Add Token Screen - addTokenButton = await queryAsync($, 'button.btn-primary.wallet-view__add-token-button') - assert.ok(addTokenButton[0], 'add token button present') - addTokenButton[0].click() - - addTokenWrapper = await queryAsync($, '.page-container') - const addTokenTabs = await queryAsync($, '.page-container__tab') - assert.equal(addTokenTabs.length, 2, 'expected number of tabs') - assert.equal(addTokenTabs[1].textContent, 'Custom Token', 'Custom Token tab present') - assert.ok(addTokenTabs[1], 'add custom token tab present') - addTokenTabs[1].click() - await timeout(1000) - - // Input token contract address - const customInput = (await findAsync(addTokenWrapper, '#custom-address'))[0] - customInput.focus() - await timeout(1000) - nativeInputValueSetter.call(customInput, '0x177af043D3A1Aed7cc5f2397C70248Fc6cDC056c') - customInput.dispatchEvent(new Event('input', { bubbles: true})) - - - // Click Next button - // nextButton = await queryAsync($, 'button.btn-primary--lg') - // assert.equal(nextButton[0].textContent, 'Next', 'next button rendered') - // nextButton[0].click() - - // // Verify symbol length error since contract address won't return symbol - const errorMessage = await queryAsync($, '#custom-symbol-helper-text') - assert.ok(errorMessage[0], 'error rendered') - - $('button.btn-default.btn--large')[0].click() - - // await timeout(100000) - - // Confirm Add token - // assert.equal( - // $('.page-container__subtitle')[0].textContent, - // 'Would you like to add these tokens?', - // 'confirm add token rendered' - // ) - // assert.ok($('button.btn-primary--lg')[0], 'confirm add token button found') - // $('button.btn-primary--lg')[0].click() - - // Verify added token image - heroBalance = await queryAsync($, '.transaction-view-balance__balance-container') - assert.ok(heroBalance, 'rendered hero balance') - assert.ok(heroBalance.find('.identicon')[0], 'token added') -} diff --git a/test/integration/lib/currency-localization.js b/test/integration/lib/currency-localization.js index 8d5acf5d0..f6b751ba2 100644 --- a/test/integration/lib/currency-localization.js +++ b/test/integration/lib/currency-localization.js @@ -25,5 +25,5 @@ async function runCurrencyLocalizationTest (assert, done) { const txView = await queryAsync($, '.transaction-view') const heroBalance = await findAsync($(txView), '.transaction-view-balance__balance') const fiatAmount = await findAsync($(heroBalance), '.transaction-view-balance__secondary-balance') - assert.equal(fiatAmount[0].textContent, '₱102,707.97 PHP') + assert.equal(fiatAmount[0].textContent, '₱102,707.97PHP') } diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js index 7f3c114e4..271dd91cf 100644 --- a/test/integration/lib/send-new-ui.js +++ b/test/integration/lib/send-new-ui.js @@ -40,7 +40,7 @@ async function customizeGas (assert, price, limit, ethFee, usdFee) { const sendGasField = await queryAsync($, '.send-v2__gas-fee-display') assert.equal( - (await findAsync(sendGasField, '.currency-display__input-wrapper > input')).val(), + (await findAsync(sendGasField, '.currency-display-component'))[0].textContent, ethFee, 'send gas field should show customized gas total' ) @@ -94,12 +94,12 @@ async function runSendFlowTest (assert, done) { sendToDropdownList.children()[2].click() const sendToAccountAddress = sendToFieldInput.val() - assert.equal(sendToAccountAddress, '0x2f8d4a878cfa04a6e60d46362f5644deab66572d', 'send to dropdown selects the correct address') + assert.equal(sendToAccountAddress, '0x2f8D4a878cFA04A6E60D46362f5644DeAb66572D', 'send to dropdown selects the correct address') const sendAmountField = await queryAsync($, '.send-v2__form-row:eq(2)') - sendAmountField.find('.currency-display')[0].click() + sendAmountField.find('.unit-input')[0].click() - const sendAmountFieldInput = await findAsync(sendAmountField, '.currency-display__input') + const sendAmountFieldInput = await findAsync(sendAmountField, '.unit-input__input') sendAmountFieldInput.val('5.1') reactTriggerChange(sendAmountField.find('input')[0]) @@ -112,9 +112,9 @@ async function runSendFlowTest (assert, done) { errorMessage = $('.send-v2__error') assert.equal(errorMessage.length, 0, 'send should stop rendering amount error message after amount is corrected') - await customizeGas(assert, 0, 21000, '0', '$0.00 USD') - await customizeGas(assert, 1, 21000, '0.000021', '$0.03 USD') - await customizeGas(assert, 500, 60000, '0.03', '$36.03 USD') + await customizeGas(assert, 0, 21000, '0ETH', '$0.00USD') + await customizeGas(assert, 1, 21000, '0.000021ETH', '$0.03USD') + await customizeGas(assert, 500, 60000, '0.03ETH', '$36.03USD') const sendButton = await queryAsync($, 'button.btn-primary.btn--large.page-container__footer-button') assert.equal(sendButton[0].textContent, 'Next', 'next button rendered') @@ -130,11 +130,11 @@ async function runSendFlowTest (assert, done) { const confirmToName = (await queryAsync($, '.sender-to-recipient__name')).last() assert.equal(confirmToName[0].textContent, 'Send Account 3', 'confirm screen should show correct to name') - const confirmScreenRowFiats = await queryAsync($, '.confirm-detail-row__fiat') + const confirmScreenRowFiats = await queryAsync($, '.confirm-detail-row__secondary') const confirmScreenGas = confirmScreenRowFiats[0] assert.equal(confirmScreenGas.textContent, '$3.60', 'confirm screen should show correct gas') const confirmScreenTotal = confirmScreenRowFiats[1] - assert.equal(confirmScreenTotal.textContent, '$2,405.36', 'confirm screen should show correct total') + assert.equal(confirmScreenTotal.textContent, '$2,405.37', 'confirm screen should show correct total') const confirmScreenBackButton = await queryAsync($, '.confirm-page-container-header__back-button') confirmScreenBackButton[0].click() @@ -150,9 +150,9 @@ async function runSendFlowTest (assert, done) { sendToFieldInputInEdit.val('0xd85a4b6a394794842887b8284293d69163007bbb') const sendAmountFieldInEdit = await queryAsync($, '.send-v2__form-row:eq(2)') - sendAmountFieldInEdit.find('.currency-display')[0].click() + sendAmountFieldInEdit.find('.unit-input')[0].click() - const sendAmountFieldInputInEdit = sendAmountFieldInEdit.find('.currency-display__input') + const sendAmountFieldInputInEdit = sendAmountFieldInEdit.find('.unit-input__input') sendAmountFieldInputInEdit.val('1.0') reactTriggerChange(sendAmountFieldInputInEdit[0]) diff --git a/test/unit/app/controllers/network-contoller-test.js b/test/unit/app/controllers/network-contoller-test.js index 822311931..7959e6cc1 100644 --- a/test/unit/app/controllers/network-contoller-test.js +++ b/test/unit/app/controllers/network-contoller-test.js @@ -47,7 +47,7 @@ describe('# Network Controller', function () { describe('#setNetworkState', function () { it('should update the network', function () { - networkController.setNetworkState(1) + networkController.setNetworkState(1, 'rpc') const networkState = networkController.getNetworkState() assert.equal(networkState, 1, 'network is 1') }) diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index b5ccf3fb5..c64c47ae9 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -375,6 +375,11 @@ describe('preferences controller', function () { await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) sandbox.assert.called(stubEnd) sandbox.assert.notCalled(stubNext) + req.method = 'wallet_watchAsset' + req.params.type = 'someasset' + await preferencesController.requestWatchAsset(req, res, asy.next, asy.end) + sandbox.assert.calledTwice(stubEnd) + sandbox.assert.notCalled(stubNext) }) it('should through error if method is supported but asset type is not', async function () { req.method = 'metamask_watchAsset' @@ -479,5 +484,24 @@ describe('preferences controller', function () { assert.equal(preferencesController.store.getState().seedWords, 'foo bar baz') }) }) + + describe('on updateFrequentRpcList', function () { + it('should add custom RPC url to state', function () { + preferencesController.addToFrequentRpcList('rpc_url', 1) + preferencesController.addToFrequentRpcList('http://localhost:8545', 1) + assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] ) + preferencesController.addToFrequentRpcList('rpc_url', 1) + assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] ) + }) + + it('should remove custom RPC url from state', function () { + preferencesController.addToFrequentRpcList('rpc_url', 1) + assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, [{ rpcUrl: 'rpc_url', chainId: 1, ticker: 'ETH', nickname: '' }] ) + preferencesController.removeFromFrequentRpcList('other_rpc_url') + preferencesController.removeFromFrequentRpcList('http://localhost:8545') + preferencesController.removeFromFrequentRpcList('rpc_url') + assert.deepEqual(preferencesController.store.getState().frequentRpcListDetail, []) + }) + }) }) diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index 5ac813b49..ea58aa560 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -158,9 +158,19 @@ describe('Transaction Controller', function () { }) describe('#addUnapprovedTransaction', function () { + const selectedAddress = '0x1678a085c290ebd122dc42cba69373b5953b831d' + + let getSelectedAddress + beforeEach(function () { + getSelectedAddress = sinon.stub(txController, 'getSelectedAddress').returns(selectedAddress) + }) + + afterEach(function () { + getSelectedAddress.restore() + }) it('should add an unapproved transaction and return a valid txMeta', function (done) { - txController.addUnapprovedTransaction({ from: '0x1678a085c290ebd122dc42cba69373b5953b831d' }) + txController.addUnapprovedTransaction({ from: selectedAddress }) .then((txMeta) => { assert(('id' in txMeta), 'should have a id') assert(('time' in txMeta), 'should have a time stamp') @@ -180,25 +190,37 @@ describe('Transaction Controller', function () { assert(txMetaFromEmit, 'txMeta is falsey') done() }) - txController.addUnapprovedTransaction({ from: '0x1678a085c290ebd122dc42cba69373b5953b831d' }) + txController.addUnapprovedTransaction({ from: selectedAddress }) .catch(done) }) it('should fail if recipient is public', function (done) { txController.networkStore = new ObservableStore(1) - txController.addUnapprovedTransaction({ from: '0x1678a085c290ebd122dc42cba69373b5953b831d', to: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2' }) + txController.addUnapprovedTransaction({ from: selectedAddress, to: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2' }) .catch((err) => { if (err.message === 'Recipient is a public account') done() else done(err) }) }) + it('should fail if the from address isn\'t the selected address', function (done) { + txController.addUnapprovedTransaction({from: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2'}) + .then(function () { + assert.fail('transaction should not have been added') + done() + }) + .catch(function () { + assert.ok('pass') + done() + }) + }) + it('should not fail if recipient is public but not on mainnet', function (done) { txController.once('newUnapprovedTx', (txMetaFromEmit) => { assert(txMetaFromEmit, 'txMeta is falsey') done() }) - txController.addUnapprovedTransaction({ from: '0x1678a085c290ebd122dc42cba69373b5953b831d', to: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2' }) + txController.addUnapprovedTransaction({ from: selectedAddress, to: '0x0d1d4e623D10F9FBA5Db95830F7d3839406C6AF2' }) .catch(done) }) }) diff --git a/test/unit/components/balance-component-test.js b/test/unit/components/balance-component-test.js deleted file mode 100644 index aa9763b72..000000000 --- a/test/unit/components/balance-component-test.js +++ /dev/null @@ -1,44 +0,0 @@ -const assert = require('assert') -const h = require('react-hyperscript') -const { createMockStore } = require('redux-test-utils') -const { shallowWithStore } = require('../../lib/render-helpers') -const BalanceComponent = require('../../../ui/app/components/balance-component') -const mockState = { - metamask: { - accounts: { abc: {} }, - network: 1, - selectedAddress: 'abc', - }, -} - -describe('BalanceComponent', function () { - let balanceComponent - let store - let component - beforeEach(function () { - store = createMockStore(mockState) - component = shallowWithStore(h(BalanceComponent), store) - balanceComponent = component.dive() - }) - - it('shows token balance and convert to fiat value based on conversion rate', function () { - const formattedBalance = '1.23 ETH' - - const tokenBalance = balanceComponent.instance().getTokenBalance(formattedBalance, false) - const fiatDisplayNumber = balanceComponent.instance().getFiatDisplayNumber(formattedBalance, 2) - - assert.equal('1.23 ETH', tokenBalance) - assert.equal(2.46, fiatDisplayNumber) - }) - - it('shows only the token balance when conversion rate is not available', function () { - const formattedBalance = '1.23 ETH' - - const tokenBalance = balanceComponent.instance().getTokenBalance(formattedBalance, false) - const fiatDisplayNumber = balanceComponent.instance().getFiatDisplayNumber(formattedBalance, 0) - - assert.equal('1.23 ETH', tokenBalance) - assert.equal('N/A', fiatDisplayNumber) - }) - -}) diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js new file mode 100644 index 000000000..df7d2ee8f --- /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, chainId, ticker, nickname, 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 deleted file mode 100644 index a2f8d8246..000000000 --- a/test/unit/ui/app/components/identicon.spec.js +++ /dev/null @@ -1,36 +0,0 @@ -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') - }) -}) |