aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/base.conf.js3
-rw-r--r--test/e2e/func.js46
-rw-r--r--test/e2e/metamask.spec.js313
-rw-r--r--test/integration/lib/add-token.js71
-rw-r--r--test/integration/lib/mascara-first-time.js32
-rw-r--r--test/integration/lib/tx-list-items.js4
-rw-r--r--test/screens/new-ui.js232
-rw-r--r--test/stub/blacklist.json1374
-rw-r--r--test/unit/actions/save_account_label_test.js35
-rw-r--r--test/unit/actions/set_account_label_test.js34
-rw-r--r--test/unit/actions/tx_test.js2
-rw-r--r--test/unit/app/ComposableObservableStore.js (renamed from test/unit/ComposableObservableStore.js)2
-rw-r--r--test/unit/app/account-import-strategies.spec.js31
-rw-r--r--test/unit/app/buy-eth-url.spec.js48
-rw-r--r--test/unit/app/controllers/address-book-controller.js (renamed from test/unit/address-book-controller.js)28
-rw-r--r--test/unit/app/controllers/blacklist-controller-test.js (renamed from test/unit/blacklist-controller-test.js)2
-rw-r--r--test/unit/app/controllers/currency-controller-test.js (renamed from test/unit/currency-controller-test.js)3
-rw-r--r--test/unit/app/controllers/infura-controller-test.js (renamed from test/unit/infura-controller-test.js)4
-rw-r--r--test/unit/app/controllers/metamask-controller-test.js550
-rw-r--r--test/unit/app/controllers/network-contoller-test.js (renamed from test/unit/network-contoller-test.js)36
-rw-r--r--test/unit/app/controllers/notice-controller-test.js (renamed from test/unit/notice-controller-test.js)4
-rw-r--r--test/unit/app/controllers/preferences-controller-test.js162
-rw-r--r--test/unit/app/controllers/token-rates-controller.js (renamed from test/unit/token-rates-controller.js)2
-rw-r--r--test/unit/app/controllers/transactions/nonce-tracker-test.js (renamed from test/unit/nonce-tracker-test.js)4
-rw-r--r--test/unit/app/controllers/transactions/pending-tx-test.js (renamed from test/unit/pending-tx-test.js)8
-rw-r--r--test/unit/app/controllers/transactions/tx-controller-test.js (renamed from test/unit/tx-controller-test.js)36
-rw-r--r--test/unit/app/controllers/transactions/tx-gas-util-test.js (renamed from test/unit/tx-gas-util-test.js)4
-rw-r--r--test/unit/app/controllers/transactions/tx-helper-test.js (renamed from test/unit/tx-helper-test.js)2
-rw-r--r--test/unit/app/controllers/transactions/tx-state-history-helper-test.js129
-rw-r--r--test/unit/app/controllers/transactions/tx-state-manager-test.js (renamed from test/unit/tx-state-manager-test.js)13
-rw-r--r--test/unit/app/controllers/transactions/tx-utils-test.js (renamed from test/unit/tx-utils-test.js)2
-rw-r--r--test/unit/app/edge-encryptor-test.js (renamed from test/unit/edge-encryptor-test.js)2
-rw-r--r--test/unit/app/message-manager-test.js (renamed from test/unit/message-manager-test.js)2
-rw-r--r--test/unit/app/nodeify-test.js (renamed from test/unit/nodeify-test.js)2
-rw-r--r--test/unit/app/pending-balance-test.js (renamed from test/unit/pending-balance-test.js)4
-rw-r--r--test/unit/app/personal-message-manager-test.js (renamed from test/unit/personal-message-manager-test.js)2
-rw-r--r--test/unit/app/seed-phrase-verifier-test.js (renamed from test/unit/seed-phrase-verifier-test.js)6
-rw-r--r--test/unit/app/util-test.js (renamed from test/unit/util-test.js)2
-rw-r--r--test/unit/metamask-controller-test.js120
-rw-r--r--test/unit/migrations/026-test.js41
-rw-r--r--test/unit/migrations/migrations-test.js (renamed from test/unit/migrations-test.js)28
-rw-r--r--test/unit/migrations/migrator-test.js (renamed from test/unit/migrator-test.js)6
-rw-r--r--test/unit/nameForAccount_test.js2
-rw-r--r--test/unit/preferences-controller-test.js48
-rw-r--r--test/unit/reducers/unlock_vault_test.js2
-rw-r--r--test/unit/tx-state-history-helper-test.js26
-rw-r--r--test/unit/tx-state-history-helper.js46
-rw-r--r--test/unit/util_test.js2
48 files changed, 1582 insertions, 1975 deletions
diff --git a/test/base.conf.js b/test/base.conf.js
index e2e9d44ba..956dce011 100644
--- a/test/base.conf.js
+++ b/test/base.conf.js
@@ -6,6 +6,9 @@ module.exports = function(config) {
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: process.cwd(),
+ // Uncomment to allow for longer timeouts
+ // browserNoActivityTimeout: 100000000,
+
browserConsoleLogOptions: {
terminal: false,
},
diff --git a/test/e2e/func.js b/test/e2e/func.js
index 733225565..8b221ce47 100644
--- a/test/e2e/func.js
+++ b/test/e2e/func.js
@@ -1,18 +1,56 @@
require('chromedriver')
+require('geckodriver')
+const path = require('path')
const webdriver = require('selenium-webdriver')
+const Command = require('selenium-webdriver/lib/command').Command
+const By = webdriver.By
-exports.delay = function delay (time) {
- return new Promise(resolve => setTimeout(resolve, time))
+module.exports = {
+ delay,
+ buildChromeWebDriver,
+ buildFirefoxWebdriver,
+ installWebExt,
+ getExtensionIdChrome,
+ getExtensionIdFirefox,
}
+function delay (time) {
+ return new Promise(resolve => setTimeout(resolve, time))
+}
-exports.buildWebDriver = function buildWebDriver (extPath) {
+function buildChromeWebDriver (extPath) {
return new webdriver.Builder()
.withCapabilities({
chromeOptions: {
args: [`load-extension=${extPath}`],
},
})
- .forBrowser('chrome')
.build()
}
+
+function buildFirefoxWebdriver () {
+ return new webdriver.Builder().build()
+}
+
+async function getExtensionIdChrome (driver) {
+ await driver.get('chrome://extensions')
+ const extensionId = await driver.executeScript('return document.querySelector("extensions-manager").shadowRoot.querySelector("extensions-view-manager extensions-item-list").shadowRoot.querySelector("extensions-item:nth-child(2)").getAttribute("id")')
+ return extensionId
+}
+
+async function getExtensionIdFirefox (driver) {
+ await driver.get('about:debugging#addons')
+ const extensionId = await driver.findElement(By.css('dd.addon-target-info-content:nth-child(6) > span:nth-child(1)')).getText()
+ return extensionId
+}
+
+async function installWebExt (driver, extension) {
+ const cmd = await new Command('moz-install-web-ext')
+ .setParameter('path', path.resolve(extension))
+ .setParameter('temporary', true)
+
+ await driver.getExecutor()
+ .defineCommand(cmd.getName(), 'POST', '/session/:sessionId/moz/addon/install')
+
+ return await driver.schedule(cmd, 'installWebExt(' + extension + ')')
+} \ No newline at end of file
diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js
index e0ff2a57e..8ec7de16c 100644
--- a/test/e2e/metamask.spec.js
+++ b/test/e2e/metamask.spec.js
@@ -4,26 +4,44 @@ const path = require('path')
const assert = require('assert')
const pify = require('pify')
const webdriver = require('selenium-webdriver')
-const By = webdriver.By
-const { delay, buildWebDriver } = require('./func')
+const { By, Key } = webdriver
+const { delay, buildChromeWebDriver, buildFirefoxWebdriver, installWebExt, getExtensionIdChrome, getExtensionIdFirefox } = require('./func')
describe('Metamask popup page', function () {
- let driver
- this.seedPhase
- this.accountAddress
+ let driver, accountAddress, tokenAddress, extensionId
+
this.timeout(0)
before(async function () {
- const extPath = path.resolve('dist/chrome')
- driver = buildWebDriver(extPath)
- await driver.get('chrome://extensions-frame')
- const elems = await driver.findElements(By.css('.extension-list-item-wrapper'))
- const extensionId = await elems[1].getAttribute('id')
- await driver.get(`chrome-extension://${extensionId}/popup.html`)
- await delay(500)
+ if (process.env.SELENIUM_BROWSER === 'chrome') {
+ const extPath = path.resolve('dist/chrome')
+ driver = buildChromeWebDriver(extPath)
+ extensionId = await getExtensionIdChrome(driver)
+ await driver.get(`chrome-extension://${extensionId}/popup.html`)
+
+ } else if (process.env.SELENIUM_BROWSER === 'firefox') {
+ const extPath = path.resolve('dist/firefox')
+ driver = buildFirefoxWebdriver()
+ await installWebExt(driver, extPath)
+ await delay(700)
+ extensionId = await getExtensionIdFirefox(driver)
+ await driver.get(`moz-extension://${extensionId}/popup.html`)
+ }
})
afterEach(async function () {
+ // logs command not supported in firefox
+ // https://github.com/SeleniumHQ/selenium/issues/2910
+ if (process.env.SELENIUM_BROWSER === 'chrome') {
+ // check for console errors
+ const errors = await checkBrowserForConsoleErrors()
+ if (errors.length) {
+ const errorReports = errors.map(err => err.message)
+ const errorMessage = `Errors found in browser console:\n${errorReports.join('\n')}`
+ this.test.error(new Error(errorMessage))
+ }
+ }
+ // gather extra data if test failed
if (this.currentTest.state === 'failed') {
await verboseReportOnFailure(this.currentTest)
}
@@ -33,105 +51,294 @@ describe('Metamask popup page', function () {
await driver.quit()
})
- describe('#onboarding', () => {
- it('should open Metamask.io', async function () {
- const tabs = await driver.getAllWindowHandles()
- await driver.switchTo().window(tabs[0])
+ describe('Setup', function () {
+
+ it('switches to Chrome extensions list', async function () {
await delay(300)
- await setProviderType('localhost')
+ const windowHandles = await driver.getAllWindowHandles()
+ await driver.switchTo().window(windowHandles[0])
+ })
+
+ it('sets provider type to localhost', async function () {
await delay(300)
+ await setProviderType('localhost')
})
- it('should match title', async () => {
+ })
+
+ describe('Account Creation', () => {
+
+ it('matches MetaMask title', async () => {
const title = await driver.getTitle()
assert.equal(title, 'MetaMask', 'title matches MetaMask')
})
- it('should show privacy notice', async () => {
+ it('shows privacy notice', async () => {
+ await delay(300)
const privacy = await driver.findElement(By.css('.terms-header')).getText()
assert.equal(privacy, 'PRIVACY NOTICE', 'shows privacy notice')
- driver.findElement(By.css('button')).click()
+ await driver.findElement(By.css('button')).click()
await delay(300)
})
- it('should show terms of use', async () => {
- await delay(300)
+ it('show terms of use', async () => {
const terms = await driver.findElement(By.css('.terms-header')).getText()
assert.equal(terms, 'TERMS OF USE', 'shows terms of use')
- await delay(300)
+ delay(300)
})
- it('should be unable to continue without scolling throught the terms of use', async () => {
+ it('checks if the TOU button is disabled', async () => {
const button = await driver.findElement(By.css('button')).isEnabled()
assert.equal(button, false, 'disabled continue button')
- const element = driver.findElement(By.linkText(
- 'Attributions'
- ))
+ const element = await driver.findElement(By.linkText('Attributions'))
await driver.executeScript('arguments[0].scrollIntoView(true)', element)
- await delay(300)
+ await delay(700)
})
- it('should be able to continue when scrolled to the bottom of terms of use', async () => {
- const button = await driver.findElement(By.css('button'))
- const buttonEnabled = await button.isEnabled()
- await delay(500)
- assert.equal(buttonEnabled, true, 'enabled continue button')
+ it('allows the button to be clicked when scrolled to the bottom of TOU', async () => {
+ const button = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-center.flex-grow > button'))
await button.click()
- await delay(300)
})
- it('should accept password with length of eight', async () => {
+ it('accepts password with length of eight', async () => {
const passwordBox = await driver.findElement(By.id('password-box'))
const passwordBoxConfirm = await driver.findElement(By.id('password-box-confirm'))
- const button = driver.findElement(By.css('button'))
+ const button = await driver.findElements(By.css('button'))
- passwordBox.sendKeys('123456789')
- passwordBoxConfirm.sendKeys('123456789')
+ await passwordBox.sendKeys('123456789')
+ await passwordBoxConfirm.sendKeys('123456789')
+ await button[0].click()
await delay(500)
- await button.click()
})
- it('should show value was created and seed phrase', async () => {
- await delay(700)
- this.seedPhase = await driver.findElement(By.css('.twelve-word-phrase')).getText()
- const continueAfterSeedPhrase = await driver.findElement(By.css('button'))
+ it('shows value was created and seed phrase', async () => {
+ await delay(300)
+ const seedPhrase = await driver.findElement(By.css('.twelve-word-phrase')).getText()
+ assert.equal(seedPhrase.split(' ').length, 12)
+ const continueAfterSeedPhrase = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > button:nth-child(4)'))
+ assert.equal(await continueAfterSeedPhrase.getText(), `I'VE COPIED IT SOMEWHERE SAFE`)
await continueAfterSeedPhrase.click()
await delay(300)
})
- it('should show lock account', async () => {
+ it('shows account address', async function () {
+ accountAddress = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > div > div:nth-child(1) > flex-column > div.flex-row > div')).getText()
+ })
+
+ it('logs out of the vault', async () => {
await driver.findElement(By.css('.sandwich-expando')).click()
await delay(500)
- await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')).click()
+ const logoutButton = await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)'))
+ assert.equal(await logoutButton.getText(), 'Log Out')
+ await logoutButton.click()
})
- it('should accept account password after lock', async () => {
+ it('accepts account password after lock', async () => {
await delay(500)
await driver.findElement(By.id('password-box')).sendKeys('123456789')
- await driver.findElement(By.css('button')).click()
+ await driver.findElement(By.id('password-box')).sendKeys(Key.ENTER)
await delay(500)
})
- it('should show QR code option', async () => {
+ it('shows QR code option', async () => {
await delay(300)
await driver.findElement(By.css('.fa-ellipsis-h')).click()
await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div:nth-child(1) > flex-column > div.name-label > div > span > i > div > div > li:nth-child(3)')).click()
await delay(300)
})
- it('should show the account address', async () => {
- this.accountAddress = await driver.findElement(By.css('.ellip-address')).getText()
+ it('checks QR code address is the same as account details address', async () => {
+ const QRaccountAddress = await driver.findElement(By.css('.ellip-address')).getText()
+ assert.equal(accountAddress.toLowerCase(), QRaccountAddress)
await driver.findElement(By.css('.fa-arrow-left')).click()
await delay(500)
})
})
- async function setProviderType(type) {
+ describe('Import Ganache seed phrase', function () {
+
+ it('logs out', async function () {
+ await driver.findElement(By.css('.sandwich-expando')).click()
+ await delay(200)
+ const logOut = await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)'))
+ assert.equal(await logOut.getText(), 'Log Out')
+ await logOut.click()
+ await delay(300)
+ })
+
+ it('restores from seed phrase', async function () {
+ const restoreSeedLink = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > div.flex-row.flex-center.flex-grow > p'))
+ assert.equal(await restoreSeedLink.getText(), 'Restore from seed phrase')
+ await restoreSeedLink.click()
+ await delay(100)
+ })
+
+ it('adds seed phrase', async function () {
+ const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent'
+ const seedTextArea = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > textarea'))
+ await seedTextArea.sendKeys(testSeedPhrase)
+
+ await driver.findElement(By.id('password-box')).sendKeys('123456789')
+ await driver.findElement(By.id('password-box-confirm')).sendKeys('123456789')
+ await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > div > button:nth-child(2)')).click()
+ await delay(500)
+ })
+
+ it('balance renders', async function () {
+ await delay(200)
+ const balance = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > div.ether-balance.ether-balance-amount > div > div > div:nth-child(1) > div:nth-child(1)'))
+ assert.equal(await balance.getText(), '100.000')
+ await delay(200)
+ })
+
+ it('sends transaction', async function () {
+ const sendButton = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > button:nth-child(4)'))
+ assert.equal(await sendButton.getText(), 'SEND')
+ await sendButton.click()
+ await delay(200)
+ })
+
+ it('adds recipient address and amount', async function () {
+ const sendTranscationScreen = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > h3:nth-child(2)')).getText()
+ assert.equal(sendTranscationScreen, 'SEND TRANSACTION')
+ const inputAddress = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section:nth-child(3) > div > input'))
+ const inputAmmount = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section:nth-child(4) > input'))
+ await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970')
+ await inputAmmount.sendKeys('10')
+ await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section:nth-child(4) > button')).click()
+ await delay(300)
+ })
+
+ it('confirms transaction', async function () {
+ await delay(300)
+ await driver.findElement(By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input')).click()
+ await delay(500)
+ })
+
+ it('finds the transaction in the transactions list', async function () {
+ const tranasactionAmount = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > section > section > div > div > div > div.ether-balance.ether-balance-amount > div > div > div > div:nth-child(1)'))
+ assert.equal(await tranasactionAmount.getText(), '10.0')
+ })
+ })
+
+ describe('Token Factory', function () {
+
+ it('navigates to token factory', async function () {
+ await driver.get('http://tokenfactory.surge.sh/')
+ })
+
+ it('navigates to create token contract link', async function () {
+ const createToken = await driver.findElement(By.css('#bs-example-navbar-collapse-1 > ul > li:nth-child(3) > a'))
+ await createToken.click()
+ })
+
+ it('adds input for token', async function () {
+ const totalSupply = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(5) > input'))
+ const tokenName = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(6) > input'))
+ const tokenDecimal = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(7) > input'))
+ const tokenSymbol = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(8) > input'))
+ const createToken = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > button'))
+
+ await totalSupply.sendKeys('100')
+ await tokenName.sendKeys('Test')
+ await tokenDecimal.sendKeys('0')
+ await tokenSymbol.sendKeys('TST')
+ await createToken.click()
+ await delay(1000)
+ })
+
+ // There is an issue with blank confirmation window in Firefox, but the button is still there and the driver is able to clicked (?.?)
+ it('confirms transaction in MetaMask popup', async function () {
+ const windowHandles = await driver.getAllWindowHandles()
+ await driver.switchTo().window(windowHandles[windowHandles.length - 1])
+ const metamaskSubmit = await driver.findElement(By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input'))
+ await metamaskSubmit.click()
+ await delay(1000)
+ })
+
+ it('switches back to Token Factory to grab the token contract address', async function () {
+ const windowHandles = await driver.getAllWindowHandles()
+ await driver.switchTo().window(windowHandles[0])
+ const tokenContactAddress = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > span:nth-child(3)'))
+ tokenAddress = await tokenContactAddress.getText()
+ await delay(500)
+ })
+
+ it('navigates back to MetaMask popup in the tab', async function () {
+ if (process.env.SELENIUM_BROWSER === 'chrome') {
+ await driver.get(`chrome-extension://${extensionId}/popup.html`)
+ } else if (process.env.SELENIUM_BROWSER === 'firefox') {
+ await driver.get(`moz-extension://${extensionId}/popup.html`)
+ }
+ await delay(700)
+ })
+ })
+
+ describe('Add Token', function () {
+
+ it('switches to the add token screen', async function () {
+ const tokensTab = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section > div > div.inactiveForm.pointer'))
+ assert.equal(await tokensTab.getText(), 'TOKENS')
+ await tokensTab.click()
+ await delay(300)
+ })
+
+ it('navigates to the add token screen', async function () {
+ const addTokenButton = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section > div.full-flex-height > div > button'))
+ assert.equal(await addTokenButton.getText(), 'ADD TOKEN')
+ await addTokenButton.click()
+ })
+
+ it('checks add token screen rendered', async function () {
+ const addTokenScreen = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.section-title.flex-row.flex-center > h2'))
+ assert.equal(await addTokenScreen.getText(), 'ADD TOKEN')
+ })
+
+ it('adds token parameters', async function () {
+ const tokenContractAddress = await driver.findElement(By.css('#token-address'))
+ await tokenContractAddress.sendKeys(tokenAddress)
+ await delay(300)
+ await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-justify-center.flex-grow.select-none > div > button')).click()
+ await delay(200)
+ })
+
+ it('checks the token balance', async function () {
+ const tokenBalance = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > ol > li:nth-child(2) > h3'))
+ assert.equal(await tokenBalance.getText(), '100 TST')
+ })
+ })
+
+ async function setProviderType (type) {
await driver.executeScript('window.metamask.setProviderType(arguments[0])', type)
}
- async function verboseReportOnFailure(test) {
- const artifactDir = `./test-artifacts/${test.title}`
+ async function checkBrowserForConsoleErrors() {
+ const ignoredLogTypes = ['WARNING']
+ const ignoredErrorMessages = [
+ // React throws error warnings on "dataset", but still sets the data-* properties correctly
+ 'Warning: Unknown prop `dataset` on ',
+ // Third-party Favicon 404s show up as errors
+ 'favicon.ico - Failed to load resource: the server responded with a status of 404 (Not Found)',
+ // React Development build - known issue blocked by test build sys
+ 'Warning: It looks like you\'re using a minified copy of the development build of React.',
+ // Redux Development build - known issue blocked by test build sys
+ 'This means that you are running a slower development build of Redux.',
+ ]
+ const browserLogs = await driver.manage().logs().get('browser')
+ const errorEntries = browserLogs.filter(entry => !ignoredLogTypes.includes(entry.level.toString()))
+ const errorObjects = errorEntries.map(entry => entry.toJSON())
+ // ignore all errors that contain a message in `ignoredErrorMessages`
+ const matchedErrorObjects = errorObjects.filter(entry => !ignoredErrorMessages.some(message => entry.message.includes(message)))
+ return matchedErrorObjects
+ }
+
+ async function verboseReportOnFailure (test) {
+ let artifactDir
+ if (process.env.SELENIUM_BROWSER === 'chrome') {
+ artifactDir = `./test-artifacts/chrome/${test.title}`
+ } else if (process.env.SELENIUM_BROWSER === 'firefox') {
+ artifactDir = `./test-artifacts/firefox/${test.title}`
+ }
const filepathBase = `${artifactDir}/test-failure`
await pify(mkdirp)(artifactDir)
// capture screenshot
diff --git a/test/integration/lib/add-token.js b/test/integration/lib/add-token.js
index 1840bdd39..e51c854d2 100644
--- a/test/integration/lib/add-token.js
+++ b/test/integration/lib/add-token.js
@@ -22,6 +22,11 @@ async function runAddTokenFlowTest (assert, done) {
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')
@@ -31,14 +36,14 @@ async function runAddTokenFlowTest (assert, done) {
addTokenButton[0].click()
// Verify Add Token screen
- let addTokenWrapper = await queryAsync($, '.add-token__wrapper')
+ let addTokenWrapper = await queryAsync($, '.page-container')
assert.ok(addTokenWrapper[0], 'add token wrapper renders')
- let addTokenTitle = await queryAsync($, '.add-token__header__title')
+ 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-secondary--lg.add-token__cancel-button')
+ const cancelAddTokenButton = await queryAsync($, 'button.btn-secondary--lg.page-container__footer-button')
assert.ok(cancelAddTokenButton[0], 'cancel add token button present')
cancelAddTokenButton.click()
@@ -50,20 +55,22 @@ async function runAddTokenFlowTest (assert, done) {
addTokenButton[0].click()
// Verify Add Token Screen
- addTokenWrapper = await queryAsync($, '.add-token__wrapper')
- addTokenTitle = await queryAsync($, '.add-token__header__title')
+ 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 queryAsync($, 'input.add-token__input')
- searchInput.val('a')
- reactTriggerChange(searchInput[0])
+ 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.add-token__token-wrapper')
+ const tokenWrapper = await queryAsync($, 'div.token-list__token')
assert.ok(tokenWrapper[0], 'token found')
- const tokenImageProp = tokenWrapper.find('.add-token__token-icon').css('background-image')
+ const tokenImageProp = tokenWrapper.find('.token-list__token-icon').css('background-image')
const tokenImageUrl = tokenImageProp.slice(5, -2)
tokenWrapper[0].click()
@@ -73,11 +80,8 @@ async function runAddTokenFlowTest (assert, done) {
nextButton[0].click()
// Confirm Add token
- assert.equal(
- $('.add-token__description')[0].textContent,
- 'Token balance(s)',
- 'confirm add token rendered'
- )
+ const confirmAddToken = await queryAsync($, '.confirm-add-token')
+ assert.ok(confirmAddToken[0], 'confirm add token rendered')
assert.ok($('button.btn-primary--lg')[0], 'confirm add token button found')
$('button.btn-primary--lg')[0].click()
@@ -91,39 +95,46 @@ async function runAddTokenFlowTest (assert, done) {
assert.ok(addTokenButton[0], 'add token button present')
addTokenButton[0].click()
- const addTokenTabs = await queryAsync($, '.add-token__header__tabs__tab')
+ 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 queryAsync($, 'input.add-token__add-custom-input')
- customInput.val('0x177af043D3A1Aed7cc5f2397C70248Fc6cDC056c')
- reactTriggerChange(customInput[0])
+ 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()
+ // 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($, '.add-token__add-custom-error-message')
+ // // 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-secondary--lg')[0].click()
- // // Confirm Add token
+ // await timeout(100000)
+
+ // Confirm Add token
// assert.equal(
- // $('.add-token__description')[0].textContent,
+ // $('.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($, '.hero-balance')
- // assert.ok(heroBalance, 'rendered hero balance')
- // assert.ok(heroBalance.find('.identicon')[0], 'token added')
+ // Verify added token image
+ heroBalance = await queryAsync($, '.hero-balance')
+ assert.ok(heroBalance, 'rendered hero balance')
+ assert.ok(heroBalance.find('.identicon')[0], 'token added')
}
diff --git a/test/integration/lib/mascara-first-time.js b/test/integration/lib/mascara-first-time.js
index 5e07ab0b4..f43a30c74 100644
--- a/test/integration/lib/mascara-first-time.js
+++ b/test/integration/lib/mascara-first-time.js
@@ -1,5 +1,4 @@
const PASSWORD = 'password123'
-const reactTriggerChange = require('react-trigger-change')
const {
timeout,
findAsync,
@@ -11,6 +10,11 @@ async function runFirstTimeUsageTest (assert, done) {
const app = await queryAsync($, '#app-content')
+ // Used to set values on TextField input component
+ const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
+ window.HTMLInputElement.prototype, 'value'
+ ).set
+
await skipNotices(app)
const welcomeButton = (await findAsync(app, '.welcome-screen__button'))[0]
@@ -21,12 +25,14 @@ async function runFirstTimeUsageTest (assert, done) {
assert.equal(title, 'Create Password', 'create password screen')
// enter password
- const pwBox = (await findAsync(app, '.first-time-flow__input'))[0]
- const confBox = (await findAsync(app, '.first-time-flow__input'))[1]
- pwBox.value = PASSWORD
- confBox.value = PASSWORD
- reactTriggerChange(pwBox)
- reactTriggerChange(confBox)
+ const pwBox = (await findAsync(app, '#create-password'))[0]
+ const confBox = (await findAsync(app, '#confirm-password'))[0]
+
+ nativeInputValueSetter.call(pwBox, PASSWORD)
+ pwBox.dispatchEvent(new Event('input', { bubbles: true}))
+
+ nativeInputValueSetter.call(confBox, PASSWORD)
+ confBox.dispatchEvent(new Event('input', { bubbles: true}))
// Create Password
const createButton = (await findAsync(app, 'button.first-time-flow__button'))[0]
@@ -71,10 +77,16 @@ async function runFirstTimeUsageTest (assert, done) {
assert.ok(lock, 'Lock menu item found')
lock.click()
- const pwBox2 = (await findAsync(app, '#password-box'))[0]
- pwBox2.value = PASSWORD
+ await timeout(1000)
+
+ const pwBox2 = (await findAsync(app, '#password'))[0]
+ pwBox2.focus()
+ await timeout(1000)
+
+ nativeInputValueSetter.call(pwBox2, PASSWORD)
+ pwBox2.dispatchEvent(new Event('input', { bubbles: true}))
- const createButton2 = (await findAsync(app, 'button.primary'))[0]
+ const createButton2 = (await findAsync(app, 'button[type="submit"]'))[0]
createButton2.click()
const detail2 = (await findAsync(app, '.wallet-view'))[0]
diff --git a/test/integration/lib/tx-list-items.js b/test/integration/lib/tx-list-items.js
index 0c0c5a77f..4856b3852 100644
--- a/test/integration/lib/tx-list-items.js
+++ b/test/integration/lib/tx-list-items.js
@@ -21,7 +21,7 @@ async function runTxListItemsTest(assert, done) {
selectState.val('tx list items')
reactTriggerChange(selectState[0])
- const metamaskLogo = await queryAsync($, '.left-menu-wrapper')
+ const metamaskLogo = await queryAsync($, '.app-header__logo-container')
assert.ok(metamaskLogo[0], 'metamask logo present')
metamaskLogo[0].click()
@@ -46,7 +46,7 @@ async function runTxListItemsTest(assert, done) {
const failedTx = txListItems[4]
const failedTxRenderedStatus = await findAsync($(failedTx), '.tx-list-status')
assert.equal(failedTxRenderedStatus[0].textContent, 'Failed', 'failedTx has correct label')
-
+
const shapeShiftTx = txListItems[5]
const shapeShiftTxStatus = await findAsync($(shapeShiftTx), '.flex-column div:eq(1)')
assert.equal(shapeShiftTxStatus[0].textContent, 'No deposits received', 'shapeShiftTx has correct status')
diff --git a/test/screens/new-ui.js b/test/screens/new-ui.js
index 91b3a9633..6b873ac85 100644
--- a/test/screens/new-ui.js
+++ b/test/screens/new-ui.js
@@ -5,29 +5,44 @@ const mkdirp = require('mkdirp')
const rimraf = require('rimraf')
const webdriver = require('selenium-webdriver')
const endOfStream = require('end-of-stream')
+const clipboardy = require('clipboardy')
+const Ethjs = require('ethjs')
const GIFEncoder = require('gifencoder')
const pngFileStream = require('png-file-stream')
const sizeOfPng = require('image-size/lib/types/png')
const By = webdriver.By
const { delay, buildWebDriver } = require('./func')
const localesIndex = require('../../app/_locales/index.json')
+// const localesIndex = []
+
+const eth = new Ethjs(new Ethjs.HttpProvider('http://localhost:8545'))
let driver
+let screenshotCount = 0
+
+captureAllScreens()
+.then(async () => {
+ // build screenshots into gif
+ console.log('building gif...')
+ await generateGif()
-captureAllScreens().catch((err) => {
+ await driver.quit()
+ process.exit()
+})
+.catch(async (err) => {
try {
console.error(err)
- verboseReportOnFailure()
- driver.quit()
+ verboseReportOnFailure({ title: 'something broke' })
} catch (err) {
console.error(err)
}
+
+ await driver.quit()
process.exit(1)
})
-async function captureAllScreens() {
- let screenshotCount = 0
+async function captureAllScreens() {
// common names
let button
let tabs
@@ -39,8 +54,7 @@ async function captureAllScreens() {
const extPath = path.resolve('dist/chrome')
driver = buildWebDriver(extPath)
await driver.get('chrome://extensions-frame')
- const elems = await driver.findElements(By.css('.extension-list-item-wrapper'))
- const extensionId = await elems[1].getAttribute('id')
+ const extensionId = await driver.executeScript('return document.querySelector("extensions-manager").shadowRoot.querySelector("extensions-view-manager extensions-item-list").shadowRoot.querySelector("#container > div.items-container > extensions-item:nth-child(2)").getAttribute("id")')
await driver.get(`chrome-extension://${extensionId}/home.html`)
await delay(500)
tabs = await driver.getAllWindowHandles()
@@ -75,10 +89,11 @@ async function captureAllScreens() {
await driver.findElement(By.css('button')).click()
await captureLanguageScreenShots('create password')
- const passwordBox = await driver.findElement(By.css('input[type=password]:nth-of-type(1)'))
- const passwordBoxConfirm = await driver.findElement(By.css('input[type=password]:nth-of-type(2)'))
- passwordBox.sendKeys('123456789')
- passwordBoxConfirm.sendKeys('123456789')
+ const password = '123456789'
+ const passwordBox = await driver.findElement(By.css('input#create-password'))
+ const passwordBoxConfirm = await driver.findElement(By.css('input#confirm-password'))
+ passwordBox.sendKeys(password)
+ passwordBoxConfirm.sendKeys(password)
await delay(500)
await captureLanguageScreenShots('choose-password-filled')
@@ -112,109 +127,123 @@ async function captureAllScreens() {
await delay(300)
await captureLanguageScreenShots('secret backup phrase - reveal')
+ const seedPhrase = await driver.findElement(By.css('.backup-phrase__secret-words')).getText()
+ const seedPhraseWords = seedPhrase.split(' ')
await driver.findElement(By.css('button')).click()
await delay(300)
await captureLanguageScreenShots('confirm secret backup phrase')
- // finish up
- console.log('building gif...')
- await generateGif()
- await driver.quit()
- return
-
- //
- // await button.click()
- // await delay(700)
- // this.seedPhase = await driver.findElement(By.css('.twelve-word-phrase')).getText()
- // await captureScreenShot('seed phrase')
- //
- // const continueAfterSeedPhrase = await driver.findElement(By.css('button'))
- // await continueAfterSeedPhrase.click()
- // await delay(300)
- // await captureScreenShot('main screen')
- //
- // await driver.findElement(By.css('.sandwich-expando')).click()
- // await delay(500)
- // await captureScreenShot('menu')
-
- // await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')).click()
- // await captureScreenShot('main screen')
- // it('should accept account password after lock', async () => {
- // await delay(500)
- // await driver.findElement(By.id('password-box')).sendKeys('123456789')
- // await driver.findElement(By.css('button')).click()
- // await delay(500)
- // })
- //
- // it('should show QR code option', async () => {
- // await delay(300)
- // await driver.findElement(By.css('.fa-ellipsis-h')).click()
- // await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div > div:nth-child(1) > flex-column > div.name-label > div > span > i > div > div > li:nth-child(3)')).click()
- // await delay(300)
- // })
- //
- // it('should show the account address', async () => {
- // this.accountAddress = await driver.findElement(By.css('.ellip-address')).getText()
- // await driver.findElement(By.css('.fa-arrow-left')).click()
- // await delay(500)
- // })
-
- async function captureLanguageScreenShots(label) {
- const nonEnglishLocales = localesIndex.filter(localeMeta => localeMeta.code !== 'en')
- // take english shot
- await captureScreenShot(`${label} (en)`)
- for (let localeMeta of nonEnglishLocales) {
- // set locale and take shot
- await setLocale(localeMeta.code)
- await delay(300)
- await captureScreenShot(`${label} (${localeMeta.code})`)
- }
- // return locale to english
- await setLocale('en')
- await delay(300)
+ // enter seed phrase
+ const seedPhraseButtons = await driver.findElements(By.css('.backup-phrase__confirm-seed-options > button'))
+ const seedPhraseButtonWords = await Promise.all(seedPhraseButtons.map(button => button.getText()))
+ for (let targetWord of seedPhraseWords) {
+ const wordIndex = seedPhraseButtonWords.indexOf(targetWord)
+ if (wordIndex === -1) throw new Error(`Captured seed phrase word "${targetWord}" not in found seed phrase button options ${seedPhraseButtonWords.join(' ')}`)
+ await driver.findElement(By.css(`.backup-phrase__confirm-seed-options > button:nth-child(${wordIndex+1})`)).click()
+ await delay(100)
}
+ await captureLanguageScreenShots('confirm secret backup phrase - words selected correctly')
- async function setLocale(code) {
- await driver.executeScript('window.metamask.updateCurrentLocale(arguments[0])', code)
- }
+ await driver.findElement(By.css('.backup-phrase__content-wrapper .first-time-flow__button')).click()
+ await delay(300)
+ await captureLanguageScreenShots('metamask post-initialize greeter screen deposit ether')
- async function setProviderType(type) {
- await driver.executeScript('window.metamask.setProviderType(arguments[0])', type)
- }
+ await driver.findElement(By.css('.page-container__header-close')).click()
+ await delay(300)
+ await captureLanguageScreenShots('metamask account main screen')
- // cleanup
- await driver.quit()
+ // account details + export private key
+ await driver.findElement(By.css('.wallet-view__name-container > .wallet-view__details-button')).click()
+ await delay(300)
+ await captureLanguageScreenShots('metamask account detail screen')
- async function cleanScreenShotDir() {
- await pify(rimraf)(`./test-artifacts/screens/`)
- }
+ await driver.findElement(By.css('.account-modal__button:nth-of-type(2)')).click()
+ await delay(300)
+ await captureLanguageScreenShots('metamask account detail export private key screen - initial')
- async function captureScreenShot(label) {
- const shotIndex = screenshotCount.toString().padStart(4, '0')
- screenshotCount++
- const artifactDir = `./test-artifacts/screens/`
- await pify(mkdirp)(artifactDir)
- // capture screenshot
- const screenshot = await driver.takeScreenshot()
- await pify(fs.writeFile)(`${artifactDir}/${shotIndex} - ${label}.png`, screenshot, { encoding: 'base64' })
- }
+ await driver.findElement(By.css('.private-key-password > input')).sendKeys(password)
+ await delay(300)
+ await captureLanguageScreenShots('metamask account detail export private key screen - password entered')
- async function generateGif(){
- // calculate screenshot size
- const screenshot = await driver.takeScreenshot()
- const pngBuffer = Buffer.from(screenshot, 'base64')
- const size = sizeOfPng.calculate(pngBuffer)
+ await driver.findElement(By.css('.btn-primary--lg.export-private-key__button')).click()
+ await delay(300)
+ await captureLanguageScreenShots('metamask account detail export private key screen - reveal key')
- // read only the english pngs into gif
- const encoder = new GIFEncoder(size.width, size.height)
- const stream = pngFileStream('./test-artifacts/screens/* (en).png')
- .pipe(encoder.createWriteStream({ repeat: 0, delay: 1000, quality: 10 }))
- .pipe(fs.createWriteStream('./test-artifacts/screens/walkthrough (en).gif'))
+ await driver.findElement(By.css('.export-private-key__button')).click()
+ await delay(300)
+ await captureLanguageScreenShots('metamask account detail export private key screen - done')
- // wait for end
- await pify(endOfStream)(stream)
+ // get eth from Ganache
+ // const viewAddressButton = await driver.findElement(By.css('.wallet-view__address'))
+ // await driver.actions({ bridge: true }).move({ origin: viewAddressButton }).perform()
+ // console.log('driver.actions', driver.actions({ bridge: true }))
+ // await delay(300)
+ // await captureLanguageScreenShots('metamask home - hover copy address')
+
+ await driver.findElement(By.css('.wallet-view__address')).click()
+ await delay(100)
+ await captureLanguageScreenShots('metamask home - hover copy address')
+
+ const primaryAddress = clipboardy.readSync()
+ await requestEther(primaryAddress)
+ // wait for block polling
+ await delay(10000)
+ await captureLanguageScreenShots('metamask home - has ether')
+
+}
+
+
+async function captureLanguageScreenShots(label) {
+ const nonEnglishLocales = localesIndex.filter(localeMeta => localeMeta.code !== 'en')
+ // take english shot
+ await captureScreenShot(`${label} (en)`)
+ for (let localeMeta of nonEnglishLocales) {
+ // set locale and take shot
+ await setLocale(localeMeta.code)
+ await delay(300)
+ await captureScreenShot(`${label} (${localeMeta.code})`)
}
+ // return locale to english
+ await setLocale('en')
+ await delay(300)
+}
+
+async function setLocale(code) {
+ await driver.executeScript('window.metamask.updateCurrentLocale(arguments[0])', code)
+}
+
+async function setProviderType(type) {
+ await driver.executeScript('window.metamask.setProviderType(arguments[0])', type)
+}
+async function cleanScreenShotDir() {
+ await pify(rimraf)(`./test-artifacts/screens/`)
+}
+
+async function captureScreenShot(label) {
+ const shotIndex = screenshotCount.toString().padStart(4, '0')
+ screenshotCount++
+ const artifactDir = `./test-artifacts/screens/`
+ await pify(mkdirp)(artifactDir)
+ // capture screenshot
+ const screenshot = await driver.takeScreenshot()
+ await pify(fs.writeFile)(`${artifactDir}/${shotIndex} - ${label}.png`, screenshot, { encoding: 'base64' })
+}
+
+async function generateGif(){
+ // calculate screenshot size
+ const screenshot = await driver.takeScreenshot()
+ const pngBuffer = Buffer.from(screenshot, 'base64')
+ const size = sizeOfPng.calculate(pngBuffer)
+
+ // read only the english pngs into gif
+ const encoder = new GIFEncoder(size.width, size.height)
+ const stream = pngFileStream('./test-artifacts/screens/* (en).png')
+ .pipe(encoder.createWriteStream({ repeat: 0, delay: 1000, quality: 10 }))
+ .pipe(fs.createWriteStream('./test-artifacts/screens/walkthrough (en).gif'))
+
+ // wait for end
+ await pify(endOfStream)(stream)
}
async function verboseReportOnFailure(test) {
@@ -228,3 +257,8 @@ async function verboseReportOnFailure(test) {
const htmlSource = await driver.getPageSource()
await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource)
}
+
+async function requestEther(address) {
+ const accounts = await eth.accounts()
+ await eth.sendTransaction({ from: accounts[0], to: address, value: 1 * 1e18, data: '0x0' })
+}
diff --git a/test/stub/blacklist.json b/test/stub/blacklist.json
deleted file mode 100644
index 6a3230b2f..000000000
--- a/test/stub/blacklist.json
+++ /dev/null
@@ -1,1374 +0,0 @@
-{
- "version": 2,
- "tolerance": 2,
- "fuzzylist": [
- "metamask.io",
- "myetherwallet.com",
- "cryptokitties.co",
- "mycrypto.com"
- ],
- "whitelist": [
- "crypto.pro",
- "ocrypto.org",
- "wecrypto.net",
- "iccrypto.io",
- "crypto.kred",
- "ohmycrypto.io",
- "spcrypto.net",
- "melcrypto.com",
- "zzcrypto.org",
- "zzcrypto.net",
- "crypto.bg",
- "mycrypto24.online",
- "acrypto.io",
- "mycrypto.ca",
- "scrypto.io",
- "mycrypto.dk",
- "mvzcrypto.com",
- "ambcrypto.com",
- "crypto.bi",
- "crypto.jobs",
- "crypto.help",
- "my.crypt.observer",
- "crypt.observer",
- "ucrypto.com",
- "cryptojobslist.com",
- "crypto.review",
- "crypto.me",
- "b3crypto.com",
- "mycrypto.ninja",
- "jkcrypto.com",
- "crypto.cr",
- "mycrypto.live",
- "yocrypto.io",
- "crypto.ba",
- "zacrypto.info",
- "mycrypto.com",
- "remix.ethereum.org",
- "metahash.io",
- "metahash.net",
- "metahash.org",
- "cryptotitties.com",
- "cryptocities.net",
- "cryptoshitties.co",
- "cryptotitties.fun",
- "cryptokitties.forsale",
- "cryptokitties.care",
- "metamate.cc",
- "metamesh.tech",
- "ico.nexus.social",
- "metamesh.org",
- "metatask.io",
- "metmask.com",
- "metarasa.com",
- "metapack.com",
- "metacase.com",
- "metafas.nl",
- "metamako.com",
- "metamast.com",
- "metamax.ru",
- "metadesk.io",
- "metadisk.com",
- "metallsk.ru",
- "metamag.fr",
- "metamaks.ru",
- "metamap.ru",
- "metamaps.cc",
- "metamats.com",
- "metamax.by",
- "metamax.com",
- "metamax.io",
- "metamuse.net",
- "metarank.com",
- "metaxas.com",
- "megamas2.ru",
- "metamask.io",
- "myetherwallet.com",
- "myethlerwallet.com",
- "ethereum.org",
- "myetheroll.com",
- "myetherapi.com",
- "ledgerwallet.com",
- "databrokerdao.com",
- "etherscan.io",
- "etherid.org",
- "ether.cards",
- "etheroll.com",
- "ethnews.com",
- "ethex.market",
- "ethereumdev.io",
- "ethereumdev.kr",
- "dether.io",
- "ethermine.org",
- "slaask.com",
- "etherbtc.io",
- "ethereal.capital",
- "etherisc.com",
- "m.famalk.net",
- "etherecho.com",
- "ethereum.os.tc",
- "theethereum.wiki",
- "metajack.im",
- "etherhub.io",
- "ethereum.network",
- "ethereum.link",
- "ethereum.com",
- "prethereum.org",
- "ethereumj.io",
- "etheraus.com",
- "ethereum.dev",
- "1ethereum.ru",
- "ethereum.nz",
- "nethereum.com",
- "metabank.com",
- "metamas.com",
- "aventus.io",
- "metabase.com",
- "etherdelta.com",
- "metabase.one",
- "cryptokitties.co",
- "remme.io",
- "jibrel.network"
- ],
- "blacklist": [
- "xn--myethrwalle-jb9e19a.com",
- "xn--myetheralle-7b9ezl.com",
- "iconfoundation.co",
- "fundrequest.info",
- "xn--myetherwale-os8e7x.com",
- "remme-ico.eu",
- "gonetwork.live",
- "token.gonetwork.pro",
- "gonetwork.pro",
- "gonetwork.eu",
- "nucleus-vision.cc",
- "jibreltoken.in",
- "dock.so",
- "dock.promo",
- "xn--mycrypt-r0a.com",
- "xn--mycrypt-g1a.com",
- "xn--mycrpto-y2a.com",
- "ethexploit.org",
- "remme.in",
- "remme.ws",
- "remme.com.ng",
- "nyeitthervvallet.com",
- "xn--myeerhwailet-ooc.com",
- "myeterhwaliot.com",
- "remme.live",
- "xn--yethewalle-to2exkhi.com",
- "myetherwallet.custom-token.com",
- "custom-token.com",
- "sale-earn.com",
- "bankera.live",
- "originprotocol.io",
- "trx.foundation",
- "tokensale.adhive.net",
- "adhive.net",
- "decentral.market",
- "cryptoexploite.com",
- "blockclain.net",
- "xn--blckchin-5za9o.info",
- "xn--blkhain-m0a4pb.info",
- "xn--blocchal-gmb8m.info",
- "xn--blocchaln-orb.info",
- "xn--blocchan-gmb7c.info",
- "xn--blockaden-lsen-5pb.com",
- "xn--blockchai-3vb.info",
- "xn--blockchai-jvb.info",
- "xn--blockchal-3vb.info",
- "xn--blockcham-ipb.info",
- "xn--blockchan-2pb.com",
- "xn--blockchan-75a.com",
- "xn--blockchan-7sb.info",
- "xn--blockchan-d5a.net",
- "xn--blockchan-dob.info",
- "xn--blockchan-ipb.com",
- "xn--blockchan-ipb.info",
- "xn--blockchan-nk7d.com",
- "xn--blockchan-xub.info",
- "xn--blockchann-4ub.com",
- "xn--blockchi-n7a50e.info",
- "xn--blockchi-o8a54d.info",
- "xn--blockchi-p99co8a.com",
- "xn--blockchim-hdb.info",
- "xn--blockchin-1xb.info",
- "xn--blockchin-61a.info",
- "xn--blockchin-61a.net",
- "xn--blockchin-6ib.info",
- "xn--blockchin-ccb.info",
- "xn--blockchin-h4a.com",
- "xn--blockchin-h4a.info",
- "xn--blockchin-hdb.info",
- "xn--blockchin-hhb.info",
- "xn--blockchin-mib.net",
- "xn--blockchin-wcb.com",
- "xn--blockchn-fza4j.com",
- "xn--blockchn-fza4j.info",
- "xn--blockchn-n7a43b.info",
- "xn--blockchn-p0a.info",
- "xn--blockchn-tx0d4p.com",
- "xn--blockclai-3vb.info",
- "xn--blockclin-hdb.com",
- "xn--blockclin-hdb.info",
- "xn--blockclin-hdb.org",
- "xn--blockflte-kirchrode-w6b.de",
- "xn--blockfltenquartett-windspiel-81c.de",
- "xn--blockhai-obb78c.info",
- "xn--blockhain-4eb.com",
- "xn--blockhain-pfb.com",
- "xn--blockhain-pfb.info",
- "xn--blockhain-zdb.info",
- "xn--blockhan-obb65a.info",
- "xn--blockhas-d6a.com",
- "xn--blockwallt-j7a.com",
- "xn--blokchai-fqb.info",
- "xn--blokchain-nfb.info",
- "xn--blokhain-28ab.info",
- "xn--bockclnain-eyb.info",
- "xn--mymoeo-zt7bzf.com",
- "xn--mymoer-nqc1368c.com",
- "xn--mymoero-c13c.com",
- "xn--mymoero-s13c.com",
- "xn--mymoneo-f63c.com",
- "xn--mymoneo-v63c.com",
- "xn--mymoneo-y53c.com",
- "xn--mymoner-j0a.com",
- "xn--mymoner-j5b.com",
- "xn--mymoner-r0a.com",
- "xn--mymoner-z0a.com",
- "xn--mymoner-z2c.com",
- "xn--mymonro-fya.com",
- "xn--mymonro-x8a.com",
- "xn--myetheallet-l58emu.com",
- "xn--myetheraet-9k2ea77h.com",
- "xn--myetheralet-ms8e21b.com",
- "xn--myetheralle-7b9exm.com",
- "xn--myetherallet-5s5f.com",
- "xn--myetherallet-fs5f.com",
- "xn--myetherewalle-1t1g.com",
- "xn--myetherllet-pl9e6k.com",
- "xn--myethervvalle-8vc.com",
- "xn--myetherwaet-61ea.com",
- "xn--myetherwaet-8eda.com",
- "xn--myetherwaet-ns8ea.com",
- "xn--myetherwale-ns8e8x.com",
- "xn--myetherwalet-0fb.com",
- "xn--myetherwalet-0z4f.com",
- "xn--myetherwalet-814f.com",
- "xn--myetherwalet-d9b.com",
- "xn--myetherwalet-h14f.com",
- "xn--myetherwalle-9me.com",
- "xn--myetherwalle-ek5f.com",
- "xn--myetherwalle-fqc.com",
- "xn--myetherwalle-opc.com",
- "xn--myetherwalle-q05f.com",
- "xn--myetherwllet-wob.com",
- "xn--myetherwllt-r7a0i.com",
- "xn--myethewaliet-9d5f.com",
- "xn--myethewalle-3ic0947g.com",
- "xn--myethewallet-0e5f.com",
- "xn--myethewallet-1kc.com",
- "xn--myethewallet-bkc.com",
- "xn--myethewallet-vof.com",
- "xn--myethewalliet-nm1g.com",
- "xn--myethewallt-kbb3019g.com",
- "xn--myethewallt-w48ew7b.com",
- "xn--myethrwalet-6qb6408g.com",
- "xn--myethrwalet-ms8e83d.com",
- "xn--myethrwallet-1db.com",
- "xn--myethrwallt-29af.com",
- "xn--myethrwallt-29as.com",
- "xn--myethrwllet-q7a31e.com",
- "xn--myethrwllet-r8a3c.com",
- "fintrux.eu",
- "refereum-ico.eu",
- "arcblock-ico.org",
- "xn--fuson-1sa.org",
- "refereum-token.com",
- "fintrux.co",
- "ico-ton.org",
- "xn--mytherwallt-cbbv.com",
- "xmoneta.co",
- "data-wallet.co",
- "tokensale.data-wallet.co",
- "xn--myeerhwallot-ooc.com",
- "xn--myeterwalet-cm8epi.com",
- "xn--myeterwalle-cm8ev6a.com",
- "rnyetherumwallet.com",
- "republic-protocol.net",
- "nyeihitervvallatt.com",
- "arcblock.eu",
- "republicprotocol.eu",
- "tokensale-fusion.com",
- "myetherwalletjoin.com",
- "medicalchian.com",
- "myeahteirwaliet.com",
- "myenhtersvvailct.com",
- "trinity-token.com",
- "xn--eo-yzs.com",
- "zilliqa.in",
- "sparc.pro",
- "myetherwallet.import-tokens.com",
- "token-gram.org",
- "xn--shapshift-e4a.com",
- "xn--shapshift-y4a.com",
- "xn--shpeshift-c2a.com",
- "xn--shpeshift-r1a.com",
- "xn--shapshift-o4a.com",
- "xn--shpeshift-w2a.com",
- "xn--shapeshft-w5a.com",
- "tokensale-fusion.org",
- "fusion-ico.com",
- "beetolen.com",
- "tokencrowdsale.online",
- "fusion.tokencrowdsale.online",
- "beetokem.com",
- "block.chaiins.in",
- "origintrail.in",
- "bit-z.ru",
- "xn--myetherallet-nu5f.com",
- "xn--mytherwalet-3qb08c.com",
- "xn--myeterwllet-cm8et1d.com",
- "xn--mytherwllet-q7a01e.com",
- "xn--biance-xt7b.com",
- "xn--bnance-wic.com",
- "xn--biance-jeb.com",
- "xn--bttrx-9za8334c.com",
- "wwwkodakcoin.com",
- "myetherwallet.uk.com",
- "kodakone.cc",
- "nyeihitervvallet.com",
- "xn--myeterwalet-cm8eoi.com",
- "nucleus.foundation",
- "beetoken-ico.com",
- "data-token.com",
- "tron-labs.com",
- "ocoin.tech",
- "aionfoundation.com",
- "ico-telegram.org",
- "nyeihitervvallat.com",
- "telegramcoin.us",
- "daddi.cloud",
- "daditoken.com",
- "blockarray.org",
- "dadi-cloud.net",
- "wanchainfunding.org",
- "ico-telegram.io",
- "iconfoundation.site",
- "iost.co",
- "beetoken-ico.eu",
- "cindicator.network",
- "wanchainetwork.org",
- "wamchain.org",
- "wanchainltd.org",
- "wanchainalliance.org",
- "nucleus-vision.net",
- "ledgerwallet.by",
- "nucleuss.vision",
- "myenhterswailct.com",
- "cobin-hood.com",
- "wanchainfoundation.org",
- "xn--polniex-ex4c.com",
- "xn--polniex-s1a.com",
- "xn--polonex-ieb.com",
- "xn--polonex-sza.com",
- "xn--polonex-zw4c.com",
- "xn--polonix-ws4c.com",
- "xn--polonix-y8a.com",
- "xn--pooniex-ojb.com",
- "gramico.info",
- "dimnsions.network",
- "www-gemini.com",
- "login-kucoin.net",
- "venchain.foundation",
- "grampreico.com",
- "tgram.cc",
- "ton-gramico.com",
- "wwwpaywithink.com",
- "coniomi.com",
- "paywithnk.com",
- "paywithlnk.com",
- "iluminatto.com.br",
- "pundix.eu",
- "xn--bttrx-esay.com",
- "xn--bttrex-w8a.com",
- "xn--bnance-bwa.com",
- "xn--shpeshift-11a.com",
- "xn--shapeshif-ts6d.com",
- "xn--shapshift-yf7d.com",
- "wwwbluzelle.com",
- "bluzelie.com",
- "nucleus-vision.org",
- "omisegonetwork.site",
- "etlherzero.com",
- "etlherdelta.com",
- "xn--condesk-0ya.com",
- "xn--condesk-sfb.com",
- "xn--coindsk-vs4c.com",
- "iexecplatform.com",
- "tongramico.com",
- "nucleus-vision.eu",
- "intchain.network",
- "wanchain.cloud",
- "bluzelle-ico.com",
- "ethzero-wallet.com",
- "xn--metherwalle-jb9et7d.com",
- "xn--coinesk-jo3c.com",
- "venchainfoundation.com",
- "myenhtersvvailot.com",
- "ether-zero.net",
- "ins.foundation",
- "nastoken.org",
- "telcointoken.com",
- "ether0.org",
- "eterzero.org",
- "bluzelle-ico.eu",
- "bleuzelle.com",
- "appcoinstoken.org",
- "xn--quanstamp-8s6d.com",
- "myehntersvvailct.com",
- "myeherwalllet.com",
- "ico-bluzelle.com",
- "bluzelle.im",
- "bluzelle.one",
- "bluzele.sale",
- "bluzele.co",
- "sether.ws",
- "xn--myetherwalet-6gf.com",
- "xn--rnyethewaliet-om1g.com",
- "rnyethervailet.com",
- "mvetherwaliet.com",
- "rnyetherwailet.com",
- "myethervaliet.com",
- "rnyethervaliet.com",
- "mvetherwalilet.com",
- "xn--myethewalie-3ic0947g.com",
- "xn--mthrwallet-z6ac3y.com",
- "xn--myeherwalie-vici.com",
- "xn--myethervvalie-8vc.com",
- "xn--mythrwallt-06acf.com",
- "xn--mtherwallet-y9a6y.com",
- "myetherwallet.applytoken.tk",
- "ethereum-zero.com",
- "quanstamptoken.tk",
- "bluzelle.network",
- "ether-wallet.org",
- "tron-wallet.info",
- "appcoinsproject.com",
- "vechain.foundation",
- "tronlab.site",
- "tronlabs.network",
- "bluzelle.cc",
- "ethblender.com",
- "ethpaperwallet.net",
- "waltontoken.org",
- "icoselfkey.org",
- "etherzeroclaim.com",
- "etherzero.promo",
- "bluzelle.pro",
- "token-selfkey.org",
- "xn--etherdlta-0f7d.com",
- "sether.in",
- "xn--ttrex-ysa9423c.com",
- "bluzelle.eu",
- "bluzelle.site",
- "gifto.tech",
- "xn--os-g7s.com",
- "selfkey.co",
- "xn--myeherwalet-ns8exy.com",
- "xn--coinelegraph-wk5f.com",
- "dai-stablecoin.com",
- "eos-token.org",
- "venchain.org",
- "gatcoins.io",
- "deepbrainchain.co",
- "myetherwalililet.info",
- "myehvterwallet.com",
- "myehterumswallet.com",
- "nucleusico.com",
- "tronlab.tech",
- "0x-project.com",
- "gift-token-events.mywebcommunity.org",
- "funfairtoken.org",
- "breadtokenapp.com",
- "cloudpetstore.com",
- "myethwalilet.com",
- "selfkeys.org",
- "wallet-ethereum.com",
- "xn--methrwallt-26ar0z.com",
- "xn--mytherwllet-r8a0c.com",
- "bluzelle.promo",
- "tokensale.bluzelle.promo",
- "cedarlake.org",
- "marketingleads4u.com",
- "cashaa.co",
- "xn--inance-hrb.com",
- "wanchain.tech",
- "zenprolocol.com",
- "ethscan.io",
- "etherscan.in",
- "props-project.com",
- "zilliaq.com",
- "reqestnetwork.com",
- "etherdelta.pw",
- "ethereum-giveaway.org",
- "mysimpletoken.org",
- "binancc.com",
- "blnance.org",
- "elherdelta.io",
- "xn--hapeshit-ez9c2y.com",
- "tenxwallet.co",
- "singularitynet.info",
- "mytlherwaliet.info",
- "iconmainnet.ml",
- "tokenselfkey.org",
- "xn--myetewallet-cm8e5y.com",
- "envione.org",
- "myetherwalletet.com",
- "claimbcd.com",
- "ripiocreditnetwork.in",
- "xn--yeterwallet-ml8euo.com",
- "ethclassicwallet.info",
- "myltherwallet.ru.com",
- "etherdella.com",
- "xn--yeterwallet-bm8ewn.com",
- "singularty.net",
- "cloudkitties.co",
- "iconfoundation.io",
- "kittystat.com",
- "gatscoin.io",
- "singularitynet.in",
- "sale.canay.io",
- "canay.io",
- "wabicoin.co",
- "envion.top",
- "sirinslabs.com",
- "tronlab.co",
- "paxful.com.ng",
- "changellyli.com",
- "ethereum-code.com",
- "xn--plonex-6va6c.com",
- "envion.co",
- "envion.cc",
- "envion.site",
- "ethereumchain.info",
- "xn--envon-1sa.org",
- "xn--btstamp-rfb.net",
- "envlon.org",
- "envion-ico.org",
- "spectivvr.org",
- "sirinlbs.com",
- "ethereumdoubler.life",
- "xn--myetherwllet-fnb.com",
- "sirin-labs.com",
- "sirin-labs.org",
- "envion.one",
- "envion.live",
- "propsproject.org",
- "propsprojects.com",
- "decentralland.org",
- "xn--metherwalet-ns8ep4b.com",
- "redpulsetoken.co",
- "propsproject.tech",
- "xn--myeterwalet-nl8emj.com",
- "powrerledger.com",
- "cryptokitties.com",
- "sirinlabs.pro",
- "sirinlabs.co",
- "sirnlabs.com",
- "superbitcoin-blockchain.info",
- "hellobloom.me",
- "mobus.network",
- "powrrledger.com",
- "xn--myeherwalet-ms8eyy.com",
- "qlink-ico.com",
- "gatcoin.in",
- "tokensale.gamefllp.com",
- "gamefllp.com",
- "xn--myeherwalle-vici.com",
- "xn--myetherwalet-39b.com",
- "xn--polonex-ffb.com",
- "xn--birex-leba.com",
- "raiden-network.org",
- "sirintabs.com",
- "xn--metherwallt-79a30a.com",
- "xn--myethrwllet-2kb3p.com",
- "myethlerwallet.eu",
- "xn--btrex-b4a.com",
- "powerrledger.com",
- "xn--cointeegraph-wz4f.com",
- "myerherwalet.com",
- "qauntstanp.com",
- "myetherermwallet.com",
- "xn--myethewalet-ns8eqq.com",
- "xn--nvion-hza.org",
- "nnyetherwallelt.ru.com",
- "ico-wacoin.com",
- "xn--myeterwalet-nl8enj.com",
- "bitcoinsilver.io",
- "t0zero.com",
- "tokensale.gizer.in",
- "gizer.in",
- "wabitoken.com",
- "gladius.ws",
- "xn--metherwallt-8bb4w.com",
- "quanttstamp.com",
- "gladius.im",
- "ethereumstorage.net",
- "powerledgerr.com",
- "xn--myeherwallet-4j5f.com",
- "quamtstamp.com",
- "quntstamp.com",
- "xn--changely-j59c.com",
- "shapeshlft.com",
- "coinbasenews.co.uk",
- "xn--metherwallet-hmb.com",
- "envoin.org",
- "powerledger.com",
- "bitstannp.net",
- "xn--myetherallet-4k5fwn.com",
- "xn--coinbas-pya.com",
- "requestt.network",
- "oracls.network",
- "sirinlabs.website",
- "powrledger.io",
- "slackconfirm.com",
- "shape-shift.io",
- "oracles-network.org",
- "xn--myeherwalle-zb9eia.com",
- "blockstack.one",
- "urtust.io",
- "bittrex.one",
- "t0-ico.com",
- "xn--cinbase-90a.com",
- "xn--metherwalet-ns8ez1g.com",
- "tzero-ico.com",
- "tzero.su",
- "tzero.website",
- "blockstack.network",
- "ico-tzero.com",
- "spectre.site",
- "tzero.pw",
- "spectre-ai.net",
- "xn--waxtokn-y8a.com",
- "dmarket.pro",
- "bittrex.com11648724328774.cf",
- "bittrex.com1987465798.ga",
- "autcus.org",
- "t-zero.org",
- "xn--zero-zxb.com",
- "myetherwalletfork.com",
- "blokclbain.info",
- "datum.sale",
- "spectre-ai.org",
- "powerledgr.com",
- "simpletoken.live",
- "sale.simpletoken.live",
- "qauntstamp.com",
- "raiden-network.com",
- "metalpayme.com",
- "quantstamp-ico.com",
- "myetherwailetclient.com",
- "biockchain.biz",
- "wallets-blockchain.com",
- "golemairdrop.com",
- "omisegoairdrop.net",
- "blodkchainwallet.info",
- "walton-chain.org",
- "elite888-ico.com",
- "bitflyerjp.com",
- "chainlinksmartcontract.com",
- "stormtoken.eu",
- "omise-go.tech",
- "saltending.com",
- "stormltoken.com",
- "xn--quanttamp-42b.com",
- "stormtoken.co",
- "storntoken.com",
- "stromtoken.com",
- "storm-token.com",
- "stormtokens.io",
- "ether-delta.com",
- "ethconnect.live",
- "ethconnect.trade",
- "xn--bttrex-3va.net",
- "quantstamp.com.co",
- "wancha.in",
- "augur-network.com",
- "quantstamp.com.ua",
- "myetherwalletmew.com",
- "myetherumwalletts.com",
- "xn--quanstamp-tmd.com",
- "quantsstamps.com",
- "changellyl.net",
- "xn--myetherwalet-1fb.com",
- "myethereumwallets.com",
- "xn--myetherwalet-e9b.com",
- "quantslamp.com",
- "metelpay.com",
- "xn--eterdelta-m75d.com",
- "linksmartcontract.com",
- "myetherwalletaccess.com",
- "myetherwalletcheck.com",
- "myetherwalletcheck.info",
- "myetherwalletconf.com",
- "myetherwalleteal.com",
- "myetherwalletec.com",
- "myetherwalletgeth.com",
- "myetherwalletmetamask.com",
- "myetherwalletmm.com",
- "myetherwalletmy.com",
- "myetherwalletnh.com",
- "myetherwalletnod.com",
- "myetherwalletrr.com",
- "myetherwalletrty.com",
- "myetherwalletsec.com",
- "myetherwalletsecure.com",
- "myetherwalletutc.com",
- "myetherwalletver.info",
- "myetherwalletview.com",
- "myetherwalletview.info",
- "myetherwalletvrf.com",
- "myetherwalletmist.com",
- "myetherwalletext.com",
- "myetherwalletjson.com",
- "mettalpay.com",
- "bricklblock.io",
- "bittrexy.com",
- "utrust.so",
- "myethierwallet.org",
- "metallpay.com",
- "kraken-wallet.com",
- "dmarkt.io",
- "etherdeltla.com",
- "unlversa.io",
- "universa.sale",
- "mercuryprotocol.live",
- "ripiocredlt.network",
- "myetlherwa11et.com",
- "dentacoin.in",
- "rdrtg.com",
- "myetherwallet.com.rdrgh.com",
- "rdrgh.com",
- "ripiocreditnetwork.co",
- "riaden.network",
- "hydrominer.biz",
- "rdrblock.com",
- "reqest.network",
- "senstoken.com",
- "myetherwallat.services",
- "ripiocredit.net",
- "xn--metherwallet-c06f.com",
- "ico.ripiocredits.com",
- "ripiocredits.com",
- "raidens.network",
- "artoken.co",
- "myetherwalletlgn.com",
- "etherblog.click",
- "stormtoken.site",
- "httpmyetherwallet.com",
- "myetherwalletverify.com",
- "byzantiumfork.com",
- "myetherwallet.com.byzantiumfork.com",
- "www-myethervvallet.com",
- "ether24.info",
- "block-v.io",
- "bittrex.cash",
- "shapishift.io",
- "ripiocerdit.network",
- "rnyetherwa11et.com",
- "claimether.com",
- "enigmatokensale.com",
- "ethereum-org.com",
- "mvetnerwallet.com",
- "myctherwallet.com",
- "myetherwaltet.com",
- "myetherwatlet.com",
- "privatix.me",
- "myetherwalletcnf.com",
- "myetherwalletver.com",
- "privatix.top",
- "privatix.pro",
- "privatex.io",
- "stormtoken.cc",
- "raiden.online",
- "stormstoken.com",
- "myetereumwallet.com",
- "stormtokens.net",
- "myetherwalletconf.info",
- "storrntoken.com",
- "worldofbattles.io",
- "ico.worldofbattles.io",
- "privatix.live",
- "riden.network",
- "raidan.network",
- "ralden.network",
- "mymyetherwallet.com",
- "myetherwallets.net",
- "myetherwalletverify.info",
- "stormxtoken.com",
- "myethereum-wallet.com",
- "myetherwallet-forkprep.pagedemo.co",
- "myetnerwailet.com",
- "www-mvetherwallet.com",
- "etheirdelta.com",
- "myetherwalletiu.com",
- "myetherwaiiett.com",
- "xn--mytherwalet-cbb87i.com",
- "xn--myethrwallet-ivb.co",
- "xn--myeterwallet-f1b.com",
- "myehterwaliet.com",
- "omegaone.co",
- "myetherwaiietw.com",
- "slack.com.ru",
- "polkodot.network",
- "request-network.net",
- "requestnetwork.live",
- "binancie.com",
- "first-eth.info",
- "myewerthwalliet.com",
- "enjincoin.pw",
- "xn--bitrex-k17b.com",
- "alrswap.io",
- "www-request.network",
- "myetnenwallet.com",
- "www-enigma.co",
- "cryptoinsidenews.com",
- "air-swap.tech",
- "launch.airswap.cc",
- "airswap.cc",
- "airswaptoken.com",
- "launch.airswap.in",
- "airswap.in",
- "security-steemit.com.mx",
- "blockchalnwallet.com",
- "blodkchainwallet.com",
- "blodkchaln.com",
- "myethereumwaiiet.com",
- "myethereumwaliet.com",
- "myethereumwalilet.com",
- "myetherswailet.com",
- "myetherswaliet.com",
- "myetherswalilet.com",
- "myetherwalilett.com",
- "myetherwalletl.com",
- "myetherwalletww.com",
- "myethereunwallet.com",
- "myethereumwallct.com",
- "myetherwaiieti.com",
- "myetherwaiiete.com",
- "upfirng.com",
- "paypie.net",
- "paypie.tech",
- "soam.co",
- "myetherwaiict.com",
- "numerai-token.com",
- "www-bankera.com",
- "vvanchain.org",
- "omisegoairdrop.com",
- "xn--enjncoin-41a.io",
- "suncontract.su",
- "myetherwaiietr.com",
- "shapeshiff.io",
- "warchain.org",
- "myethwallett.com",
- "myethervvaliet.com",
- "wanchains.org",
- "etherparty.in",
- "enjincoin.me",
- "etiam.io",
- "invest.smartlands.tech",
- "smartlands.tech",
- "enijncoin.io",
- "wanchain.network",
- "nimiq.su",
- "enjincoin.sale",
- "tenxwallet.io",
- "golem-network.net",
- "myyethwallet.ml",
- "mywetherwailiet.com",
- "omg-omise.com",
- "district0x.tech",
- "centra-token.com",
- "etherdetla.com",
- "etnerparty.io",
- "etherdelta.su",
- "myetherwallett.neocities.org",
- "myetherwallet-secure.com",
- "myethereumwalletntw.info",
- "real-markets.io",
- "wallet-ethereum.org",
- "request-network.com",
- "shapeshifth.io",
- "shiapeshift.in",
- "coin.red-puise.com",
- "ibittreix.com",
- "coinkbase.com",
- "cindicator.pro",
- "myetherwallet.com.ailogin.me",
- "eventchain.co",
- "kinkik.in",
- "myetherumwalletview.com",
- "protostokenhub.com",
- "coinrbase.com",
- "myetherwalletlogin.com",
- "omisegotoken.com",
- "myethereumwalletntw.com",
- "reall.markets",
- "cobinhood.org",
- "cobinhood.io",
- "happy-coin.org",
- "bitfinex.com.co",
- "bitfienex.com",
- "iconn.foundation",
- "centra.vip",
- "smartcontract.live",
- "icon.community",
- "air-token.com",
- "centra.credit",
- "myetherwallet-singin.com",
- "smartcontractlink.com",
- "shapesshift.io",
- "0xtoken.io",
- "augurproject.co",
- "ethereumus.one",
- "myetherumwalet.com",
- "myetherwalletsignin.com",
- "change-bank.org",
- "charge-bank.com",
- "myetherwalletsingin.com",
- "myetherwalletcontract.com",
- "change-bank.io",
- "chainlink.tech",
- "myetherwallet-confirm.com",
- "tokensale.kybernet.network",
- "kybernet.network",
- "kyberr.network",
- "kybernetwork.io",
- "myetherwalletconfirm.com",
- "kvnuke.github.io",
- "kin.kikpro.co",
- "myethereumwallet.co.uk",
- "tokensale-kyber.network",
- "kyber-network.co",
- "tokensale.kyber-network.co",
- "pyro0.github.io",
- "tokensale.kyber.digital",
- "kyber.digital",
- "omise-go.me",
- "my.etherwallet.com.de",
- "bepartof.change-bank.co",
- "change-bank.co",
- "enigma-tokens.co",
- "coinbase.com.eslogin.co",
- "xn--bittrx-mva.com",
- "ethrdelta.github.io",
- "etherdellta.com",
- "ico-nexus.social",
- "red-pulse.tech",
- "bitj0b.io",
- "xn--bttrex-bwa.com",
- "kin-klk.com",
- "kin-crowdsale.com",
- "ethedelta.com",
- "coindash.su",
- "myethwallet.co.uk",
- "swarm.credit",
- "myethereumwallet.uk",
- "iconexu.social",
- "wanchain.co",
- "enigrna.co",
- "linknetwork.co",
- "qtum-token.com",
- "omisego.com.co",
- "rivetzintl.org",
- "etherdelta.one",
- "the-ether.pro",
- "etherdelta.gitnub.io",
- "kirkik.com",
- "monetha.ltd",
- "vlberate.io",
- "ethereumwallet-kr.info",
- "omise-go.org",
- "iconexus.social",
- "bittirrex.com",
- "aventus.pro",
- "atlant.solutions",
- "aventus.group",
- "metamak.io",
- "omise.com.co",
- "herotokens.io",
- "starbase.pro",
- "etherdelta.githulb.io",
- "herotoken.co",
- "kinico.net",
- "dmarket.ltd",
- "etherdelta.gilthub.io",
- "golem-network.com",
- "etnerscan.io",
- "bllttriex.com",
- "monetha.me",
- "monetha.co",
- "monetha-crowdsale.com",
- "starbase.tech",
- "aventus-crowdsale.com",
- "shapeshift.pro",
- "bllttrex.com",
- "kickico.co",
- "statustoken.im",
- "bilttrex.com",
- "tenxpay.io",
- "bittrex.ltd",
- "metalpay.im",
- "aragon.im",
- "coindash.tech",
- "decentraland.tech",
- "decentraland.pro",
- "status-token.com",
- "bittrex.cam",
- "enigmatoken.com",
- "unocoin.company",
- "unocoin.fund",
- "0xproject.io",
- "0xtoken.com",
- "numerai.tech",
- "decentraiand.org",
- "blockcrein.info",
- "blockchealn.info",
- "bllookchain.info",
- "blockcbhain.info",
- "myetherwallet.com.ethpromonodes.com",
- "mettamask.io",
- "tokenswap.org",
- "netherum.com",
- "etherexx.org",
- "etherume.io",
- "ethereum.plus",
- "ehtereum.org",
- "etereurm.org",
- "etheream.com",
- "ethererum.org",
- "ethereum.io",
- "etherdelta-glthub.com",
- "cryptoalliance.herokuapp.com",
- "bitspark2.com",
- "indorsetoken.com",
- "iconexus.tk",
- "iconexus.ml",
- "iconexus.ga",
- "iconexus.cf",
- "etherwallet.online",
- "wallet-ethereum.net",
- "bitsdigit.com",
- "etherswap.org",
- "eos.ac",
- "uasfwallet.com",
- "ziber.io",
- "multiply-ethereum.info",
- "bittrex.comze.com",
- "karbon.vacau.com",
- "etherdelta.gitlhub.io",
- "etherdelta.glthub.io",
- "digitaldevelopersfund.vacau.com",
- "district-0x.io",
- "coin-dash.com",
- "coindash.ru",
- "district0x.net",
- "aragonproject.io",
- "coin-wallet.info",
- "coinswallet.info",
- "contribute-status.im",
- "ether-api.com",
- "ether-wall.com",
- "mycoinwallet.net",
- "ethereumchamber.com",
- "ethereumchamber.net",
- "ethereumchest.com",
- "ethewallet.com",
- "myetherwallet.com.vc",
- "myetherwallet.com.pe",
- "myetherwallet.us.com",
- "myetherwallet.com.u0387831.cp.regruhosting.ru",
- "myethereumwallet.su",
- "myetherweb.com.de",
- "myetherieumwallet.com",
- "myetehrwallet.com",
- "myeterwalet.com",
- "myetherwaiiet.com",
- "myetherwallet.info",
- "myetherwallet.ch",
- "myetherwallet.om",
- "myethervallet.com",
- "myetherwallet.com.cm",
- "myetherwallet.com.co",
- "myetherwallet.com.de",
- "myetherwallet.com.gl",
- "myetherwallet.com.im",
- "myetherwallet.com.ua",
- "secure-myetherwallet.com",
- "update-myetherwallet.com",
- "wwwmyetherwallet.com",
- "myeatherwallet.com",
- "myetharwallet.com",
- "myelherwallel.com",
- "myetherwaillet.com",
- "myetherwaliet.com",
- "myetherwallel.com",
- "myetherwallet.cam",
- "myetherwallet.cc",
- "myetherwallet.co",
- "myetherwallet.cm",
- "myetherwallet.cz",
- "myetherwallet.org",
- "myetherwallet.tech",
- "myetherwallet.top",
- "myetherwallet.net",
- "myetherwallet.ru.com",
- "myetherwallet.com.ru",
- "metherwallet.com",
- "myetrerwallet.com",
- "myetlerwallet.com",
- "myethterwallet.com",
- "myethwallet.io",
- "myethterwallet.co",
- "myehterwallet.co",
- "myaetherwallet.com",
- "myetthterwallet.com",
- "myetherwallet.one",
- "myelterwallet.com",
- "myetherwallet.gdn",
- "myetherwallt.com",
- "myeterwallet.com",
- "myeteherwallet.com",
- "myethearwailet.com",
- "myetherwallelt.com",
- "myetherwallett.com",
- "etherwallet.org",
- "myetherewallet.com",
- "myeherwallet.com",
- "myethcrwallet.com",
- "myetherwallet.link",
- "myetherwallets.com",
- "myethearwaillet.com",
- "myethearwallet.com",
- "myetherawllet.com",
- "myethereallet.com",
- "myetherswallet.com",
- "myetherwalet.com",
- "myetherwaller.com",
- "myetherwalliet.com",
- "myetherwllet.com",
- "etherwallet.io",
- "myetherwallet.ca",
- "myetherwallet.me",
- "myetherwallet.ru",
- "myetherwallet.xyz",
- "myetherwallte.com",
- "myethirwallet.com",
- "myethrewallet.com",
- "etherwallet.net",
- "maetherwallet.com",
- "meyetherwallet.com",
- "my.ether-wallet.pw",
- "myehterwallet.com",
- "myeitherwallet.com",
- "myelherwallet.com",
- "myeltherwallet.com",
- "myerherwallet.com",
- "myethearwalet.com",
- "myetherewalle.com",
- "myethervvallet.com",
- "myetherwallent.com",
- "myetherwallet.fm",
- "myetherwalllet.com",
- "myetherwalltet.com",
- "myetherwollet.com",
- "myetlherwalet.com",
- "myetlherwallet.com",
- "rnyetherwallet.com",
- "etherclassicwallet.com",
- "omg-omise.co",
- "omise-go.com",
- "omise-go.net",
- "omise-omg.com",
- "omise-go.io",
- "tenx-tech.com",
- "bitclaive.com",
- "tokensale-tenx.tech",
- "ubiqcoin.org",
- "metamask.com",
- "ethtrade.io",
- "myetcwallet.com",
- "account-kigo.net",
- "bitcoin-wallet.net",
- "blocklichan.info",
- "bloclkicihan.info",
- "coindash.ml",
- "eos-bonus.com",
- "eos-io.info",
- "ether-wallet.net",
- "ethereum-wallet.info",
- "ethereum-wallet.net",
- "ethereumchest.net",
- "reservations-kigo.net",
- "reservations-lodgix.com",
- "secure-liverez.com",
- "secure-onerooftop.com",
- "settings-liverez.com",
- "software-liverez.com",
- "software-lodgix.com",
- "unhackableetherwallets.com",
- "www-myetherwallet.com",
- "etherwallet.co.za",
- "etherwalletchain.com",
- "etherwallets.net",
- "etherwallets.nl",
- "my-ethwallet.com",
- "my.ether-wallet.co",
- "myetherwallet.com.am",
- "myetherwallet.com.ht",
- "myetherwalletcom.com",
- "myehterwailet.com",
- "xn--myetherwalle-xoc.com",
- "xn--myetherwalle-44i.com",
- "xn--myetherwalle-xhk.com",
- "xn--myetherwallt-cfb.com",
- "xn--myetherwallt-6tb.com",
- "xn--myetherwallt-xub.com",
- "xn--myetherwallt-ovb.com",
- "xn--myetherwallt-fwb.com",
- "xn--myetherwallt-5wb.com",
- "xn--myetherwallt-jzi.com",
- "xn--myetherwallt-2ck.com",
- "xn--myetherwallt-lok.com",
- "xn--myetherwallt-lsl.com",
- "xn--myetherwallt-ce6f.com",
- "xn--myetherwalet-mcc.com",
- "xn--myetherwalet-xhf.com",
- "xn--myetherwalet-lcc.com",
- "xn--myetherwaet-15ba.com",
- "xn--myetherwalet-whf.com",
- "xn--myetherwaet-v2ea.com",
- "xn--myetherwllet-59a.com",
- "xn--myetherwllet-jbb.com",
- "xn--myetherwllet-wbb.com",
- "xn--myetherwllet-9bb.com",
- "xn--myetherwllet-ncb.com",
- "xn--myetherwllet-0cb.com",
- "xn--myetherwllet-5nb.com",
- "xn--myetherwllet-ktd.com",
- "xn--myetherwllet-mre.com",
- "xn--myetherwllet-76e.com",
- "xn--myetherwllet-o0l.com",
- "xn--myetherwllet-c45f.com",
- "xn--myetherallet-ejn.com",
- "xn--myethewallet-4nf.com",
- "xn--myethewallet-iof.com",
- "xn--myethewallet-mpf.com",
- "xn--myethewallet-6bk.com",
- "xn--myethewallet-i31f.com",
- "xn--myethrwallet-feb.com",
- "xn--myethrwallt-fbbf.com",
- "xn--myethrwallet-seb.com",
- "xn--myethrwallt-rbbf.com",
- "xn--myethrwallet-5eb.com",
- "xn--myethrwallt-3bbf.com",
- "xn--myethrwallet-0tb.com",
- "xn--myethrwallt-tpbf.com",
- "xn--myethrwallet-rub.com",
- "xn--myethrwallt-iqbf.com",
- "xn--myethrwallet-ivb.com",
- "xn--myethrwallt-6qbf.com",
- "xn--myethrwallet-8vb.com",
- "xn--myethrwallt-vrbf.com",
- "xn--myethrwallet-zwb.com",
- "xn--myethrwallt-ksbf.com",
- "xn--myethrwallet-dzi.com",
- "xn--myethrwallt-wbif.com",
- "xn--myethrwallet-wck.com",
- "xn--myethrwallt-skjf.com",
- "xn--myethrwallet-fok.com",
- "xn--myethrwallt-fvjf.com",
- "xn--myethrwallet-fsl.com",
- "xn--myethrwallt-fwkf.com",
- "xn--myethrwallet-5d6f.com",
- "xn--myethrwallt-319ef.com",
- "xn--myeterwallet-ufk.com",
- "xn--myeterwallet-nrl.com",
- "xn--myeterwallet-von.com",
- "xn--myeterwallet-jl6c.com",
- "xn--myeherwallet-ooc.com",
- "xn--myeherwalle-6hci.com",
- "xn--myeherwallet-v4i.com",
- "xn--myeherwalle-zgii.com",
- "xn--myeherwallet-ohk.com",
- "xn--myeherwalle-6oji.com",
- "xn--mytherwallet-ceb.com",
- "xn--mythrwallet-cbbc.com",
- "xn--mythrwallt-c7acf.com",
- "xn--mytherwallet-peb.com",
- "xn--mythrwallet-obbc.com",
- "xn--mythrwallt-n7acf.com",
- "xn--mytherwallet-2eb.com",
- "xn--mythrwallet-0bbc.com",
- "xn--mythrwallt-y7acf.com",
- "xn--mytherwallet-xtb.com",
- "xn--mythrwallet-qpbc.com",
- "xn--mythrwallt-jlbcf.com",
- "xn--mytherwallet-oub.com",
- "xn--mythrwallet-fqbc.com",
- "xn--mythrwallt-5lbcf.com",
- "xn--mythrwallet-3qbc.com",
- "xn--mythrwallt-smbcf.com",
- "xn--mytherwallet-5vb.com",
- "xn--mythrwallet-srbc.com",
- "xn--mythrwallt-fnbcf.com",
- "xn--mytherwallet-wwb.com",
- "xn--mythrwallet-hsbc.com",
- "xn--mythrwallt-1nbcf.com",
- "xn--mytherwallet-9yi.com",
- "xn--mythrwallet-tbic.com",
- "xn--mythrwallt-dnhcf.com",
- "xn--mytherwallet-tck.com",
- "xn--mythrwallet-pkjc.com",
- "xn--mythrwallt-lsicf.com",
- "xn--mytherwallet-cok.com",
- "xn--mythrwallet-cvjc.com",
- "xn--mythrwallt-c2icf.com",
- "xn--mytherwallet-csl.com",
- "xn--mythrwallet-cwkc.com",
- "xn--mythrwallt-c0jcf.com",
- "xn--mytherwallet-2d6f.com",
- "xn--mythrwallet-019ec.com",
- "xn--mythrwallt-yq3ecf.com",
- "xn--metherwallet-qlb.com",
- "xn--metherwallet-1uf.com",
- "xn--metherwallet-iyi.com",
- "xn--metherwallet-zhk.com",
- "xn--metherwallet-3ml.com",
- "xn--mytherwallet-fvb.com",
- "xn--myetherwallt-7db.com",
- "xn--myetherwallt-leb.com",
- "xn--myetherwallt-yeb.com",
- "xn--yetherwallet-vjf.com",
- "xn--yetherwallet-dfk.com",
- "xn--yetherwallet-1t1f.com",
- "xn--yetherwallet-634f.com",
- "xn--myeherwallet-fpc.com",
- "xn--myethewallt-crb.com",
- "xn--metherwallet-1vc.com",
- "xn--myeherwallt-kbb8039g.com",
- "xn--myeherwallet-vk5f.com",
- "xn--yethewallet-iw8ejl.com",
- "xn--bittrx-th8b.com",
- "xn--polniex-n0a.com",
- "thekey.vin",
- "thekey-vip.com",
- "digitexftures.com",
- "ethzero-wallet.org",
- "zeepln.io",
- "wepowers.network",
- "wepower.vision"
- ]
-}
diff --git a/test/unit/actions/save_account_label_test.js b/test/unit/actions/save_account_label_test.js
deleted file mode 100644
index c5ffd6cbf..000000000
--- a/test/unit/actions/save_account_label_test.js
+++ /dev/null
@@ -1,35 +0,0 @@
-// var jsdom = require('mocha-jsdom')
-var assert = require('assert')
-var freeze = require('deep-freeze-strict')
-var path = require('path')
-
-var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
-var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
-
-describe('SAVE_ACCOUNT_LABEL', function () {
- it('updates the state.metamask.identities[:i].name property of the state to the action.value.label', function () {
- var initialState = {
- metamask: {
- identities: {
- foo: {
- name: 'bar',
- },
- },
- },
- }
- freeze(initialState)
-
- const action = {
- type: actions.SAVE_ACCOUNT_LABEL,
- value: {
- account: 'foo',
- label: 'baz',
- },
- }
- freeze(action)
-
- var resultingState = reducers(initialState, action)
- assert.equal(resultingState.metamask.identities.foo.name, action.value.label)
- })
-})
-
diff --git a/test/unit/actions/set_account_label_test.js b/test/unit/actions/set_account_label_test.js
new file mode 100644
index 000000000..53ea1d130
--- /dev/null
+++ b/test/unit/actions/set_account_label_test.js
@@ -0,0 +1,34 @@
+const assert = require('assert')
+const freeze = require('deep-freeze-strict')
+const path = require('path')
+
+const actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
+const reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
+
+describe('SET_ACCOUNT_LABEL', function () {
+ it('updates the state.metamask.identities[:i].name property of the state to the action.value.label', function () {
+ const initialState = {
+ metamask: {
+ identities: {
+ foo: {
+ name: 'bar',
+ },
+ },
+ },
+ }
+ freeze(initialState)
+
+ const action = {
+ type: actions.SET_ACCOUNT_LABEL,
+ value: {
+ account: 'foo',
+ label: 'baz',
+ },
+ }
+ freeze(action)
+
+ const resultingState = reducers(initialState, action)
+ assert.equal(resultingState.metamask.identities.foo.name, action.value.label)
+ })
+})
+
diff --git a/test/unit/actions/tx_test.js b/test/unit/actions/tx_test.js
index b6a691860..c110f71fc 100644
--- a/test/unit/actions/tx_test.js
+++ b/test/unit/actions/tx_test.js
@@ -9,7 +9,7 @@ var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'redu
describe('tx confirmation screen', function () {
beforeEach(function () {
- this.sinon = sinon.sandbox.create()
+ this.sinon = sinon.createSandbox()
})
afterEach(function () {
diff --git a/test/unit/ComposableObservableStore.js b/test/unit/app/ComposableObservableStore.js
index 3fba200c1..aa8abd463 100644
--- a/test/unit/ComposableObservableStore.js
+++ b/test/unit/app/ComposableObservableStore.js
@@ -1,5 +1,5 @@
const assert = require('assert')
-const ComposableObservableStore = require('../../app/scripts/lib/ComposableObservableStore')
+const ComposableObservableStore = require('../../../app/scripts/lib/ComposableObservableStore')
const ObservableStore = require('obs-store')
describe('ComposableObservableStore', () => {
diff --git a/test/unit/app/account-import-strategies.spec.js b/test/unit/app/account-import-strategies.spec.js
new file mode 100644
index 000000000..83cfaeb3e
--- /dev/null
+++ b/test/unit/app/account-import-strategies.spec.js
@@ -0,0 +1,31 @@
+const assert = require('assert')
+const path = require('path')
+const accountImporter = require('../../../app/scripts/account-import-strategies/index')
+const ethUtil = require('ethereumjs-util')
+
+describe('Account Import Strategies', function () {
+ const privkey = '0x4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553'
+ const json = '{"version":3,"id":"dbb54385-0a99-437f-83c0-647de9f244c3","address":"a7f92ce3fba24196cf6f4bd2e1eb3db282ba998c","Crypto":{"ciphertext":"bde13d9ade5c82df80281ca363320ce254a8a3a06535bbf6ffdeaf0726b1312c","cipherparams":{"iv":"fbf93718a57f26051b292f072f2e5b41"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"7ffe00488319dec48e4c49a120ca49c6afbde9272854c64d9541c83fc6acdffe","n":8192,"r":8,"p":1},"mac":"2adfd9c4bc1cdac4c85bddfb31d9e21a684e0e050247a70c5698facf6b7d4681"}}'
+
+ it('imports a private key and strips 0x prefix', async function () {
+ const importPrivKey = await accountImporter.importAccount('Private Key', [ privkey ])
+ assert.equal(importPrivKey, ethUtil.stripHexPrefix(privkey))
+ })
+
+ it('fails when password is incorrect for keystore', async function () {
+ const wrongPassword = 'password2'
+
+ try {
+ await accountImporter.importAccount('JSON File', [ json, wrongPassword])
+ } catch (error) {
+ assert.equal(error.message, 'Key derivation failed - possibly wrong passphrase')
+ }
+ })
+
+ it('imports json string and password to return a private key', async function () {
+ const fileContentsPassword = 'password1'
+ const importJson = await accountImporter.importAccount('JSON File', [ json, fileContentsPassword])
+ assert.equal(importJson, '0x5733876abe94146069ce8bcbabbde2677f2e35fa33e875e92041ed2ac87e5bc7')
+ })
+
+})
diff --git a/test/unit/app/buy-eth-url.spec.js b/test/unit/app/buy-eth-url.spec.js
new file mode 100644
index 000000000..36646fa68
--- /dev/null
+++ b/test/unit/app/buy-eth-url.spec.js
@@ -0,0 +1,48 @@
+const assert = require('assert')
+const getBuyEthUrl = require('../../../app/scripts/lib/buy-eth-url')
+
+describe('', function () {
+ const mainnet = {
+ network: '1',
+ amount: 5,
+ address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
+ }
+ const ropsten = {
+ network: '3',
+ }
+ const rinkeby = {
+ network: '4',
+ }
+ const kovan = {
+ network: '42',
+ }
+
+ it('returns coinbase url with amount and address for network 1', function () {
+ const coinbaseUrl = getBuyEthUrl(mainnet)
+ const coinbase = coinbaseUrl.match(/(https:\/\/buy.coinbase.com)/)
+ const amount = coinbaseUrl.match(/(amount)\D\d/)
+ const address = coinbaseUrl.match(/(address)(.*)(?=&)/)
+
+ assert.equal(coinbase[0], 'https://buy.coinbase.com')
+ assert.equal(amount[0], 'amount=5')
+ assert.equal(address[0], 'address=0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc')
+
+ })
+
+ it('returns metamask ropsten faucet for network 3', function () {
+ const ropstenUrl = getBuyEthUrl(ropsten)
+ assert.equal(ropstenUrl, 'https://faucet.metamask.io/')
+ })
+
+ it('returns rinkeby dapp for network 4', function () {
+ const rinkebyUrl = getBuyEthUrl(rinkeby)
+ assert.equal(rinkebyUrl, 'https://www.rinkeby.io/')
+ })
+
+ it('returns kovan github test faucet for network 42', function () {
+ const kovanUrl = getBuyEthUrl(kovan)
+ assert.equal(kovanUrl, 'https://github.com/kovan-testnet/faucet')
+ })
+
+})
+
diff --git a/test/unit/address-book-controller.js b/test/unit/app/controllers/address-book-controller.js
index 655c9022c..dc4b8e3ff 100644
--- a/test/unit/address-book-controller.js
+++ b/test/unit/app/controllers/address-book-controller.js
@@ -1,26 +1,26 @@
const assert = require('assert')
-const AddressBookController = require('../../app/scripts/controllers/address-book')
+const AddressBookController = require('../../../../app/scripts/controllers/address-book')
-const mockKeyringController = {
- memStore: {
- getState: function () {
- return {
- identities: {
- '0x0aaa': {
- address: '0x0aaa',
- name: 'owned',
- },
+const stubPreferencesStore = {
+ getState: function () {
+ return {
+ identities: {
+ '0x0aaa': {
+ address: '0x0aaa',
+ name: 'owned',
},
- }
- },
+ },
+ }
},
-}
+};
describe('address-book-controller', function () {
var addressBookController
beforeEach(function () {
- addressBookController = new AddressBookController({}, mockKeyringController)
+ addressBookController = new AddressBookController({
+ preferencesStore: stubPreferencesStore,
+ })
})
describe('addres book management', function () {
diff --git a/test/unit/blacklist-controller-test.js b/test/unit/app/controllers/blacklist-controller-test.js
index cbf73d3e5..085641777 100644
--- a/test/unit/blacklist-controller-test.js
+++ b/test/unit/app/controllers/blacklist-controller-test.js
@@ -1,5 +1,5 @@
const assert = require('assert')
-const BlacklistController = require('../../app/scripts/controllers/blacklist')
+const BlacklistController = require('../../../../app/scripts/controllers/blacklist')
describe('blacklist controller', function () {
let blacklistController
diff --git a/test/unit/currency-controller-test.js b/test/unit/app/controllers/currency-controller-test.js
index 63ab60f9e..1941d1c43 100644
--- a/test/unit/currency-controller-test.js
+++ b/test/unit/app/controllers/currency-controller-test.js
@@ -3,7 +3,7 @@ global.fetch = global.fetch || require('isomorphic-fetch')
const assert = require('assert')
const nock = require('nock')
-const CurrencyController = require('../../app/scripts/controllers/currency')
+const CurrencyController = require('../../../../app/scripts/controllers/currency')
describe('currency-controller', function () {
var currencyController
@@ -45,7 +45,6 @@ describe('currency-controller', function () {
currencyController.updateConversionRate()
.then(function () {
var result = currencyController.getConversionRate()
- console.log('currencyController.getConversionRate:', result)
assert.equal(typeof result, 'number')
done()
}).catch(function (err) {
diff --git a/test/unit/infura-controller-test.js b/test/unit/app/controllers/infura-controller-test.js
index 605305efa..7bd95dd4b 100644
--- a/test/unit/infura-controller-test.js
+++ b/test/unit/app/controllers/infura-controller-test.js
@@ -1,6 +1,6 @@
const assert = require('assert')
const sinon = require('sinon')
-const InfuraController = require('../../app/scripts/controllers/infura')
+const InfuraController = require('../../../../app/scripts/controllers/infura')
describe('infura-controller', function () {
let infuraController, sandbox, networkStatus
@@ -8,7 +8,7 @@ describe('infura-controller', function () {
before(async function () {
infuraController = new InfuraController()
- sandbox = sinon.sandbox.create()
+ sandbox = sinon.createSandbox()
sinon.stub(infuraController, 'checkInfuraNetworkStatus').resolves(response)
networkStatus = await infuraController.checkInfuraNetworkStatus()
})
diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js
new file mode 100644
index 000000000..4bc16e65e
--- /dev/null
+++ b/test/unit/app/controllers/metamask-controller-test.js
@@ -0,0 +1,550 @@
+const assert = require('assert')
+const sinon = require('sinon')
+const clone = require('clone')
+const nock = require('nock')
+const createThoughStream = require('through2').obj
+const MetaMaskController = require('../../../../app/scripts/metamask-controller')
+const blacklistJSON = require('eth-phishing-detect/src/config')
+const firstTimeState = require('../../../../app/scripts/first-time-state')
+
+const currentNetworkId = 42
+const DEFAULT_LABEL = 'Account 1'
+const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'
+const TEST_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'
+const TEST_SEED_ALT = 'setup olympic issue mobile velvet surge alcohol burger horse view reopen gentle'
+const TEST_ADDRESS_ALT = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'
+
+describe('MetaMaskController', function () {
+ let metamaskController
+ const sandbox = sinon.createSandbox()
+ const noop = () => {}
+
+ beforeEach(function () {
+
+ nock('https://api.infura.io')
+ .persist()
+ .get('/v2/blacklist')
+ .reply(200, blacklistJSON)
+
+ nock('https://api.infura.io')
+ .get('/v1/ticker/ethusd')
+ .reply(200, '{"base": "ETH", "quote": "USD", "bid": 288.45, "ask": 288.46, "volume": 112888.17569277, "exchange": "bitfinex", "total_volume": 272175.00106721005, "num_exchanges": 8, "timestamp": 1506444677}')
+
+ nock('https://api.infura.io')
+ .get('/v1/ticker/ethjpy')
+ .reply(200, '{"base": "ETH", "quote": "JPY", "bid": 32300.0, "ask": 32400.0, "volume": 247.4616071, "exchange": "kraken", "total_volume": 247.4616071, "num_exchanges": 1, "timestamp": 1506444676}')
+
+ nock('https://api.infura.io')
+ .persist()
+ .get(/.*/)
+ .reply(200)
+
+ metamaskController = new MetaMaskController({
+ showUnapprovedTx: noop,
+ showUnconfirmedMessage: noop,
+ encryptor: {
+ encrypt: function (password, object) {
+ this.object = object
+ return Promise.resolve()
+ },
+ decrypt: function () {
+ return Promise.resolve(this.object)
+ },
+ },
+ initState: clone(firstTimeState),
+ })
+ sandbox.spy(metamaskController.keyringController, 'createNewVaultAndKeychain')
+ sandbox.spy(metamaskController.keyringController, 'createNewVaultAndRestore')
+ })
+
+ afterEach(function () {
+ nock.cleanAll()
+ sandbox.restore()
+ })
+
+ describe('#getGasPrice', function () {
+
+ it('gives the 50th percentile lowest accepted gas price from recentBlocksController', async function () {
+ const realRecentBlocksController = metamaskController.recentBlocksController
+ metamaskController.recentBlocksController = {
+ store: {
+ getState: () => {
+ return {
+ recentBlocks: [
+ { gasPrices: [ '0x3b9aca00', '0x174876e800'] },
+ { gasPrices: [ '0x3b9aca00', '0x174876e800'] },
+ { gasPrices: [ '0x174876e800', '0x174876e800' ]},
+ { gasPrices: [ '0x174876e800', '0x174876e800' ]},
+ ],
+ }
+ },
+ },
+ }
+
+ const gasPrice = metamaskController.getGasPrice()
+ assert.equal(gasPrice, '0x3b9aca00', 'accurately estimates 50th percentile accepted gas price')
+
+ metamaskController.recentBlocksController = realRecentBlocksController
+ })
+ })
+
+ describe('#createNewVaultAndKeychain', function () {
+ it('can only create new vault on keyringController once', async function () {
+ const selectStub = sandbox.stub(metamaskController, 'selectFirstIdentity')
+
+ const password = 'a-fake-password'
+
+ await metamaskController.createNewVaultAndKeychain(password)
+ await metamaskController.createNewVaultAndKeychain(password)
+
+ assert(metamaskController.keyringController.createNewVaultAndKeychain.calledOnce)
+
+ selectStub.reset()
+ })
+ })
+
+ describe('#createNewVaultAndRestore', function () {
+ it('should be able to call newVaultAndRestore despite a mistake.', async function () {
+ const password = 'what-what-what'
+ await metamaskController.createNewVaultAndRestore(password, TEST_SEED.slice(0, -1)).catch((e) => null)
+ await metamaskController.createNewVaultAndRestore(password, TEST_SEED)
+
+ assert(metamaskController.keyringController.createNewVaultAndRestore.calledTwice)
+ })
+
+ it('should clear previous identities after vault restoration', async () => {
+ await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED)
+ assert.deepEqual(metamaskController.getState().identities, {
+ [TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL },
+ })
+
+ await metamaskController.preferencesController.setAccountLabel(TEST_ADDRESS, 'Account Foo')
+ assert.deepEqual(metamaskController.getState().identities, {
+ [TEST_ADDRESS]: { address: TEST_ADDRESS, name: 'Account Foo' },
+ })
+
+ await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED_ALT)
+ assert.deepEqual(metamaskController.getState().identities, {
+ [TEST_ADDRESS_ALT]: { address: TEST_ADDRESS_ALT, name: DEFAULT_LABEL },
+ })
+ })
+ })
+
+ describe('#getApi', function () {
+ let getApi, state
+
+ beforeEach(function () {
+ getApi = metamaskController.getApi()
+ })
+
+ it('getState', function (done) {
+ getApi.getState((err, res) => {
+ if (err) {
+ done(err)
+ } else {
+ state = res
+ }
+ })
+ assert.deepEqual(state, metamaskController.getState())
+ done()
+ })
+
+ })
+
+ describe('preferencesController', function () {
+
+ it('defaults useBlockie to false', function () {
+ assert.equal(metamaskController.preferencesController.store.getState().useBlockie, false)
+ })
+
+ it('setUseBlockie to true', function () {
+ metamaskController.setUseBlockie(true, noop)
+ assert.equal(metamaskController.preferencesController.store.getState().useBlockie, true)
+ })
+
+ })
+
+ describe('#selectFirstIdentity', function () {
+ let identities, address
+
+ beforeEach(function () {
+ address = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'
+ identities = {
+ '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': {
+ 'address': address,
+ 'name': 'Account 1',
+ },
+ '0xc42edfcc21ed14dda456aa0756c153f7985d8813': {
+ 'address': '0xc42edfcc21ed14dda456aa0756c153f7985d8813',
+ 'name': 'Account 2',
+ },
+ }
+ metamaskController.preferencesController.store.updateState({ identities })
+ metamaskController.selectFirstIdentity()
+ })
+
+ it('changes preferences controller select address', function () {
+ const preferenceControllerState = metamaskController.preferencesController.store.getState()
+ assert.equal(preferenceControllerState.selectedAddress, address)
+ })
+
+ it('changes metamask controller selected address', function () {
+ const metamaskState = metamaskController.getState()
+ assert.equal(metamaskState.selectedAddress, address)
+ })
+ })
+
+ describe('#setCustomRpc', function () {
+ const customRPC = 'https://custom.rpc/'
+ let rpcTarget
+
+ beforeEach(function () {
+
+ nock('https://custom.rpc')
+ .post('/')
+ .reply(200)
+
+ rpcTarget = metamaskController.setCustomRpc(customRPC)
+ })
+
+ afterEach(function () {
+ nock.cleanAll()
+ })
+
+ it('returns custom RPC that when called', async function () {
+ assert.equal(await rpcTarget, customRPC)
+ })
+
+ it('changes the network controller rpc', function () {
+ const networkControllerState = metamaskController.networkController.store.getState()
+ assert.equal(networkControllerState.provider.rpcTarget, customRPC)
+ })
+ })
+
+ describe('#setCurrentCurrency', function () {
+ let defaultMetaMaskCurrency
+
+ beforeEach(function () {
+ defaultMetaMaskCurrency = metamaskController.currencyController.getCurrentCurrency()
+ })
+
+ it('defaults to usd', function () {
+ assert.equal(defaultMetaMaskCurrency, 'usd')
+ })
+
+ it('sets currency to JPY', function () {
+ metamaskController.setCurrentCurrency('JPY', noop)
+ assert.equal(metamaskController.currencyController.getCurrentCurrency(), 'JPY')
+ })
+ })
+
+ describe('#createShapeshifttx', function () {
+ let depositAddress, depositType, shapeShiftTxList
+
+ beforeEach(function () {
+ nock('https://shapeshift.io')
+ .get('/txStat/3EevLFfB4H4XMWQwYCgjLie1qCAGpd2WBc')
+ .reply(200, '{"status": "no_deposits", "address": "3EevLFfB4H4XMWQwYCgjLie1qCAGpd2WBc"}')
+
+ depositAddress = '3EevLFfB4H4XMWQwYCgjLie1qCAGpd2WBc'
+ depositType = 'ETH'
+ shapeShiftTxList = metamaskController.shapeshiftController.store.getState().shapeShiftTxList
+ })
+
+ it('creates a shapeshift tx', async function () {
+ metamaskController.createShapeShiftTx(depositAddress, depositType)
+ assert.equal(shapeShiftTxList[0].depositAddress, depositAddress)
+ })
+
+ })
+
+ describe('#addNewAccount', function () {
+ let addNewAccount
+
+ beforeEach(function () {
+ addNewAccount = metamaskController.addNewAccount()
+ })
+
+ it('errors when an primary keyring is does not exist', async function () {
+ try {
+ await addNewAccount
+ assert.equal(1 === 0)
+ } catch (e) {
+ assert.equal(e.message, 'MetamaskController - No HD Key Tree found')
+ }
+ })
+ })
+
+ describe('#verifyseedPhrase', function () {
+ let seedPhrase, getConfigSeed
+
+ it('errors when no keying is provided', async function () {
+ try {
+ await metamaskController.verifySeedPhrase()
+ } catch (error) {
+ assert.equal(error.message, 'MetamaskController - No HD Key Tree found')
+ }
+ })
+
+ beforeEach(async function () {
+ await metamaskController.createNewVaultAndKeychain('password')
+ seedPhrase = await metamaskController.verifySeedPhrase()
+ })
+
+ it('#placeSeedWords should match the initially created vault seed', function () {
+
+ metamaskController.placeSeedWords((err, result) => {
+ if (err) {
+ console.log(err)
+ } else {
+ getConfigSeed = metamaskController.configManager.getSeedWords()
+ assert.equal(result, seedPhrase)
+ assert.equal(result, getConfigSeed)
+ }
+ })
+ assert.equal(getConfigSeed, undefined)
+ })
+
+ it('#addNewAccount', async function () {
+ await metamaskController.addNewAccount()
+ const getAccounts = await metamaskController.keyringController.getAccounts()
+ assert.equal(getAccounts.length, 2)
+ })
+ })
+
+ describe('#resetAccount', function () {
+
+ beforeEach(function () {
+ const selectedAddressStub = sinon.stub(metamaskController.preferencesController, 'getSelectedAddress')
+ const getNetworkstub = sinon.stub(metamaskController.txController.txStateManager, 'getNetwork')
+
+ selectedAddressStub.returns('0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc')
+ getNetworkstub.returns(42)
+
+ metamaskController.txController.txStateManager._saveTxList([
+ { id: 1, status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: {from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'} },
+ { id: 2, status: 'rejected', metamaskNetworkId: 32, txParams: {} },
+ { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {from: '0xB09d8505E1F4EF1CeA089D47094f5DD3464083d4'} },
+ ])
+ })
+
+ it('wipes transactions from only the correct network id and with the selected address', async function () {
+ await metamaskController.resetAccount()
+ assert.equal(metamaskController.txController.txStateManager.getTx(1), undefined)
+ })
+ })
+
+ describe('#clearSeedWordCache', function () {
+
+ it('should have set seed words', function () {
+ metamaskController.configManager.setSeedWords('test words')
+ const getConfigSeed = metamaskController.configManager.getSeedWords()
+ assert.equal(getConfigSeed, 'test words')
+ })
+
+ it('should clear config seed phrase', function () {
+ metamaskController.configManager.setSeedWords('test words')
+ metamaskController.clearSeedWordCache((err, result) => {
+ if (err) console.log(err)
+ })
+ const getConfigSeed = metamaskController.configManager.getSeedWords()
+ assert.equal(getConfigSeed, null)
+ })
+
+ })
+
+ describe('#setCurrentLocale', function () {
+
+ it('checks the default currentLocale', function () {
+ const preferenceCurrentLocale = metamaskController.preferencesController.store.getState().currentLocale
+ assert.equal(preferenceCurrentLocale, undefined)
+ })
+
+ it('sets current locale in preferences controller', function () {
+ metamaskController.setCurrentLocale('ja', noop)
+ const preferenceCurrentLocale = metamaskController.preferencesController.store.getState().currentLocale
+ assert.equal(preferenceCurrentLocale, 'ja')
+ })
+
+ })
+
+ describe('#newUnsignedMessage', function () {
+
+ let msgParams, metamaskMsgs, messages, msgId
+
+ const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'
+ const data = '0x43727970746f6b697474696573'
+
+ beforeEach(async function () {
+
+ await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED_ALT)
+
+ msgParams = {
+ 'from': address,
+ 'data': data,
+ }
+
+ metamaskController.newUnsignedMessage(msgParams, noop)
+ metamaskMsgs = metamaskController.messageManager.getUnapprovedMsgs()
+ messages = metamaskController.messageManager.messages
+ msgId = Object.keys(metamaskMsgs)[0]
+ messages[0].msgParams.metamaskId = parseInt(msgId)
+ })
+
+ it('persists address from msg params', function () {
+ assert.equal(metamaskMsgs[msgId].msgParams.from, address)
+ })
+
+ it('persists data from msg params', function () {
+ assert.equal(metamaskMsgs[msgId].msgParams.data, data)
+ })
+
+ it('sets the status to unapproved', function () {
+ assert.equal(metamaskMsgs[msgId].status, 'unapproved')
+ })
+
+ it('sets the type to eth_sign', function () {
+ assert.equal(metamaskMsgs[msgId].type, 'eth_sign')
+ })
+
+ it('rejects the message', function () {
+ const msgIdInt = parseInt(msgId)
+ metamaskController.cancelMessage(msgIdInt, noop)
+ assert.equal(messages[0].status, 'rejected')
+ })
+
+ it('errors when signing a message', async function () {
+ try {
+ await metamaskController.signMessage(messages[0].msgParams)
+ } catch (error) {
+ assert.equal(error.message, 'message length is invalid')
+ }
+ })
+ })
+
+ describe('#newUnsignedPersonalMessage', function () {
+
+ it('errors with no from in msgParams', function () {
+ const msgParams = {
+ 'data': data,
+ }
+ metamaskController.newUnsignedPersonalMessage(msgParams, function (error) {
+ assert.equal(error.message, 'MetaMask Message Signature: from field is required.')
+ })
+ })
+
+ let msgParams, metamaskPersonalMsgs, personalMessages, msgId
+
+ const address = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'
+ const data = '0x43727970746f6b697474696573'
+
+ beforeEach(async function () {
+
+ await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED_ALT)
+
+ msgParams = {
+ 'from': address,
+ 'data': data,
+ }
+
+ metamaskController.newUnsignedPersonalMessage(msgParams, noop)
+ metamaskPersonalMsgs = metamaskController.personalMessageManager.getUnapprovedMsgs()
+ personalMessages = metamaskController.personalMessageManager.messages
+ msgId = Object.keys(metamaskPersonalMsgs)[0]
+ personalMessages[0].msgParams.metamaskId = parseInt(msgId)
+ })
+
+ it('persists address from msg params', function () {
+ assert.equal(metamaskPersonalMsgs[msgId].msgParams.from, address)
+ })
+
+ it('persists data from msg params', function () {
+ assert.equal(metamaskPersonalMsgs[msgId].msgParams.data, data)
+ })
+
+ it('sets the status to unapproved', function () {
+ assert.equal(metamaskPersonalMsgs[msgId].status, 'unapproved')
+ })
+
+ it('sets the type to personal_sign', function () {
+ assert.equal(metamaskPersonalMsgs[msgId].type, 'personal_sign')
+ })
+
+ it('rejects the message', function () {
+ const msgIdInt = parseInt(msgId)
+ metamaskController.cancelPersonalMessage(msgIdInt, noop)
+ assert.equal(personalMessages[0].status, 'rejected')
+ })
+
+ it('errors when signing a message', async function () {
+ await metamaskController.signPersonalMessage(personalMessages[0].msgParams)
+ assert.equal(metamaskPersonalMsgs[msgId].status, 'signed')
+ assert.equal(metamaskPersonalMsgs[msgId].rawSig, '0x6a1b65e2b8ed53cf398a769fad24738f9fbe29841fe6854e226953542c4b6a173473cb152b6b1ae5f06d601d45dd699a129b0a8ca84e78b423031db5baa734741b')
+ })
+ })
+
+ describe('#setupUntrustedCommunication', function () {
+ let streamTest
+
+ const phishingUrl = 'decentral.market'
+
+ afterEach(function () {
+ streamTest.end()
+ })
+
+ it('sets up phishing stream for untrusted communication ', async function () {
+ await metamaskController.blacklistController.updatePhishingList()
+
+ streamTest = createThoughStream((chunk, enc, cb) => {
+ assert.equal(chunk.name, 'phishing')
+ assert.equal(chunk.data.hostname, phishingUrl)
+ cb()
+ })
+ // console.log(streamTest)
+ metamaskController.setupUntrustedCommunication(streamTest, phishingUrl)
+ })
+ })
+
+ describe('#setupTrustedCommunication', function () {
+ let streamTest
+
+ afterEach(function () {
+ streamTest.end()
+ })
+
+ it('sets up controller dnode api for trusted communication', function (done) {
+ streamTest = createThoughStream((chunk, enc, cb) => {
+ assert.equal(chunk.name, 'controller')
+ cb()
+ done()
+ })
+
+ metamaskController.setupTrustedCommunication(streamTest, 'mycrypto.com')
+ })
+ })
+
+ describe('#markAccountsFound', function () {
+ it('adds lost accounts to config manager data', function () {
+ metamaskController.markAccountsFound(noop)
+ const configManagerData = metamaskController.configManager.getData()
+ assert.deepEqual(configManagerData.lostAccounts, [])
+ })
+ })
+
+ describe('#markPasswordForgotten', function () {
+ it('adds and sets forgottenPassword to config data to true', function () {
+ metamaskController.markPasswordForgotten(noop)
+ const configManagerData = metamaskController.configManager.getData()
+ assert.equal(configManagerData.forgottenPassword, true)
+ })
+ })
+
+ describe('#unMarkPasswordForgotten', function () {
+ it('adds and sets forgottenPassword to config data to false', function () {
+ metamaskController.unMarkPasswordForgotten(noop)
+ const configManagerData = metamaskController.configManager.getData()
+ assert.equal(configManagerData.forgottenPassword, false)
+ })
+ })
+
+})
diff --git a/test/unit/network-contoller-test.js b/test/unit/app/controllers/network-contoller-test.js
index 2b905718b..789850ef3 100644
--- a/test/unit/network-contoller-test.js
+++ b/test/unit/app/controllers/network-contoller-test.js
@@ -1,19 +1,17 @@
const assert = require('assert')
const nock = require('nock')
-const NetworkController = require('../../app/scripts/controllers/network')
+const NetworkController = require('../../../../app/scripts/controllers/network')
const {
getNetworkDisplayName,
- getNetworkEndpoints,
-} = require('../../app/scripts/controllers/network/util')
+} = require('../../../../app/scripts/controllers/network/util')
-const { createTestProviderTools } = require('../stub/provider')
+const { createTestProviderTools } = require('../../../stub/provider')
const providerResultStub = {}
-const provider = createTestProviderTools({ scaffold: providerResultStub }).provider
describe('# Network Controller', function () {
let networkController
const noop = () => {}
- const networkControllerProviderInit = {
+ const networkControllerProviderConfig = {
getAccounts: noop,
}
@@ -24,11 +22,9 @@ describe('# Network Controller', function () {
.post('/metamask')
.reply(200)
- networkController = new NetworkController({
- provider,
- })
+ networkController = new NetworkController()
- networkController.initializeProvider(networkControllerProviderInit, provider)
+ networkController.initializeProvider(networkControllerProviderConfig)
})
afterEach(function () {
@@ -38,7 +34,7 @@ describe('# Network Controller', function () {
describe('network', function () {
describe('#provider', function () {
it('provider should be updatable without reassignment', function () {
- networkController.initializeProvider(networkControllerProviderInit, provider)
+ networkController.initializeProvider(networkControllerProviderConfig)
const proxy = networkController._proxy
proxy.setTarget({ test: true, on: () => {} })
assert.ok(proxy.test)
@@ -59,12 +55,6 @@ describe('# Network Controller', function () {
})
})
- describe('#getRpcAddressForType', function () {
- it('should return the right rpc address', function () {
- const rpcTarget = networkController.getRpcAddressForType('mainnet')
- assert.equal(rpcTarget, 'https://mainnet.infura.io/metamask', 'returns the right rpcAddress')
- })
- })
describe('#setProviderType', function () {
it('should update provider.type', function () {
networkController.setProviderType('mainnet')
@@ -76,16 +66,11 @@ describe('# Network Controller', function () {
const loading = networkController.isNetworkLoading()
assert.ok(loading, 'network is loading')
})
- it('should set the right rpcTarget', function () {
- networkController.setProviderType('mainnet')
- const rpcTarget = networkController.getProviderConfig().rpcTarget
- assert.equal(rpcTarget, 'https://mainnet.infura.io/metamask', 'returns the right rpcAddress')
- })
})
})
})
-describe('# Network utils', () => {
+describe('Network utils', () => {
it('getNetworkDisplayName should return the correct network name', () => {
const tests = [
{
@@ -114,9 +99,4 @@ describe('# Network utils', () => {
tests.forEach(({ input, expected }) => assert.equal(getNetworkDisplayName(input), expected))
})
-
- it('getNetworkEndpoints should return the correct endpoints', () => {
- assert.equal(getNetworkEndpoints('networkBeta').ropsten, 'https://ropsten.infura.io/metamask2')
- assert.equal(getNetworkEndpoints('network').rinkeby, 'https://rinkeby.infura.io/metamask')
- })
})
diff --git a/test/unit/notice-controller-test.js b/test/unit/app/controllers/notice-controller-test.js
index 09eeda15c..e78b69623 100644
--- a/test/unit/notice-controller-test.js
+++ b/test/unit/app/controllers/notice-controller-test.js
@@ -1,6 +1,6 @@
const assert = require('assert')
-const configManagerGen = require('../lib/mock-config-manager')
-const NoticeController = require('../../app/scripts/notice-controller')
+const configManagerGen = require('../../../lib/mock-config-manager')
+const NoticeController = require('../../../../app/scripts/notice-controller')
describe('notice-controller', function () {
var noticeController
diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js
new file mode 100644
index 000000000..e5e751b57
--- /dev/null
+++ b/test/unit/app/controllers/preferences-controller-test.js
@@ -0,0 +1,162 @@
+const assert = require('assert')
+const PreferencesController = require('../../../../app/scripts/controllers/preferences')
+
+describe('preferences controller', function () {
+ let preferencesController
+
+ beforeEach(() => {
+ preferencesController = new PreferencesController()
+ })
+
+ describe('setAddresses', function () {
+ it('should keep a map of addresses to names and addresses in the store', function () {
+ preferencesController.setAddresses([
+ '0xda22le',
+ '0x7e57e2',
+ ])
+
+ const {identities} = preferencesController.store.getState()
+ assert.deepEqual(identities, {
+ '0xda22le': {
+ name: 'Account 1',
+ address: '0xda22le',
+ },
+ '0x7e57e2': {
+ name: 'Account 2',
+ address: '0x7e57e2',
+ },
+ })
+ })
+
+ it('should replace its list of addresses', function () {
+ preferencesController.setAddresses([
+ '0xda22le',
+ '0x7e57e2',
+ ])
+ preferencesController.setAddresses([
+ '0xda22le77',
+ '0x7e57e277',
+ ])
+
+ const {identities} = preferencesController.store.getState()
+ assert.deepEqual(identities, {
+ '0xda22le77': {
+ name: 'Account 1',
+ address: '0xda22le77',
+ },
+ '0x7e57e277': {
+ name: 'Account 2',
+ address: '0x7e57e277',
+ },
+ })
+ })
+ })
+
+ describe('setAccountLabel', function () {
+ it('should update a label for the given account', function () {
+ preferencesController.setAddresses([
+ '0xda22le',
+ '0x7e57e2',
+ ])
+
+ assert.deepEqual(preferencesController.store.getState().identities['0xda22le'], {
+ name: 'Account 1',
+ address: '0xda22le',
+ })
+
+
+ preferencesController.setAccountLabel('0xda22le', 'Dazzle')
+ assert.deepEqual(preferencesController.store.getState().identities['0xda22le'], {
+ name: 'Dazzle',
+ address: '0xda22le',
+ })
+ })
+ })
+
+ describe('getTokens', function () {
+ it('should return an empty list initially', async function () {
+ await preferencesController.setSelectedAddress('0x7e57e2')
+
+ const tokens = preferencesController.getTokens()
+ assert.equal(tokens.length, 0, 'empty list of tokens')
+ })
+ })
+
+ describe('addToken', function () {
+ it('should add that token to its state', async function () {
+ const address = '0xabcdef1234567'
+ const symbol = 'ABBR'
+ const decimals = 5
+
+ await preferencesController.setSelectedAddress('0x7e57e2')
+ await preferencesController.addToken(address, symbol, decimals)
+
+ const tokens = preferencesController.getTokens()
+ assert.equal(tokens.length, 1, 'one token added')
+
+ const added = tokens[0]
+ assert.equal(added.address, address, 'set address correctly')
+ assert.equal(added.symbol, symbol, 'set symbol correctly')
+ assert.equal(added.decimals, decimals, 'set decimals correctly')
+ })
+
+ it('should allow updating a token value', async function () {
+ const address = '0xabcdef1234567'
+ const symbol = 'ABBR'
+ const decimals = 5
+
+ await preferencesController.setSelectedAddress('0x7e57e2')
+ await preferencesController.addToken(address, symbol, decimals)
+
+ const newDecimals = 6
+ await preferencesController.addToken(address, symbol, newDecimals)
+
+ const tokens = preferencesController.getTokens()
+ assert.equal(tokens.length, 1, 'one token added')
+
+ const added = tokens[0]
+ assert.equal(added.address, address, 'set address correctly')
+ assert.equal(added.symbol, symbol, 'set symbol correctly')
+ assert.equal(added.decimals, newDecimals, 'updated decimals correctly')
+ })
+
+ it('should allow adding tokens to two separate addresses', async function () {
+ const address = '0xabcdef1234567'
+ const symbol = 'ABBR'
+ const decimals = 5
+
+ await preferencesController.setSelectedAddress('0x7e57e2')
+ await preferencesController.addToken(address, symbol, decimals)
+ assert.equal(preferencesController.getTokens().length, 1, 'one token added for 1st address')
+
+ await preferencesController.setSelectedAddress('0xda22le')
+ await preferencesController.addToken(address, symbol, decimals)
+ assert.equal(preferencesController.getTokens().length, 1, 'one token added for 2nd address')
+ })
+ })
+
+ describe('removeToken', function () {
+ it('should remove the only token from its state', async function () {
+ await preferencesController.setSelectedAddress('0x7e57e2')
+ await preferencesController.addToken('0xa', 'A', 5)
+ await preferencesController.removeToken('0xa')
+
+ const tokens = preferencesController.getTokens()
+ assert.equal(tokens.length, 0, 'one token removed')
+ })
+
+ it('should remove a token from its state', async function () {
+ await preferencesController.setSelectedAddress('0x7e57e2')
+ await preferencesController.addToken('0xa', 'A', 4)
+ await preferencesController.addToken('0xb', 'B', 5)
+ await preferencesController.removeToken('0xa')
+
+ const tokens = preferencesController.getTokens()
+ assert.equal(tokens.length, 1, 'one token removed')
+
+ const [token1] = tokens
+ assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
+ })
+ })
+})
+
diff --git a/test/unit/token-rates-controller.js b/test/unit/app/controllers/token-rates-controller.js
index a49547313..28e583d8d 100644
--- a/test/unit/token-rates-controller.js
+++ b/test/unit/app/controllers/token-rates-controller.js
@@ -1,6 +1,6 @@
const assert = require('assert')
const sinon = require('sinon')
-const TokenRatesController = require('../../app/scripts/controllers/token-rates')
+const TokenRatesController = require('../../../../app/scripts/controllers/token-rates')
const ObservableStore = require('obs-store')
describe('TokenRatesController', () => {
diff --git a/test/unit/nonce-tracker-test.js b/test/unit/app/controllers/transactions/nonce-tracker-test.js
index cf26945d3..fc852458c 100644
--- a/test/unit/nonce-tracker-test.js
+++ b/test/unit/app/controllers/transactions/nonce-tracker-test.js
@@ -1,6 +1,6 @@
const assert = require('assert')
-const NonceTracker = require('../../app/scripts/controllers/transactions/nonce-tracker')
-const MockTxGen = require('../lib/mock-tx-gen')
+const NonceTracker = require('../../../../../app/scripts/controllers/transactions/nonce-tracker')
+const MockTxGen = require('../../../../lib/mock-tx-gen')
let providerResultStub = {}
describe('Nonce Tracker', function () {
diff --git a/test/unit/pending-tx-test.js b/test/unit/app/controllers/transactions/pending-tx-test.js
index 001b86dd1..e7705c594 100644
--- a/test/unit/pending-tx-test.js
+++ b/test/unit/app/controllers/transactions/pending-tx-test.js
@@ -3,9 +3,9 @@ const ethUtil = require('ethereumjs-util')
const EthTx = require('ethereumjs-tx')
const ObservableStore = require('obs-store')
const clone = require('clone')
-const { createTestProviderTools } = require('../stub/provider')
-const PendingTransactionTracker = require('../../app/scripts/controllers/transactions/pending-tx-tracker')
-const MockTxGen = require('../lib/mock-tx-gen')
+const { createTestProviderTools } = require('../../../../stub/provider')
+const PendingTransactionTracker = require('../../../../../app/scripts/controllers/transactions/pending-tx-tracker')
+const MockTxGen = require('../../../../lib/mock-tx-gen')
const sinon = require('sinon')
const noop = () => true
const currentNetworkId = 42
@@ -294,7 +294,7 @@ describe('PendingTransactionTracker', function () {
})
afterEach(() => {
- pendingTxTracker.publishTransaction.reset()
+ pendingTxTracker.publishTransaction.restore()
})
it('should publish the transaction', function (done) {
diff --git a/test/unit/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js
index ddd921652..1f32a0f37 100644
--- a/test/unit/tx-controller-test.js
+++ b/test/unit/app/controllers/transactions/tx-controller-test.js
@@ -4,9 +4,9 @@ const EthTx = require('ethereumjs-tx')
const EthjsQuery = require('ethjs-query')
const ObservableStore = require('obs-store')
const sinon = require('sinon')
-const TransactionController = require('../../app/scripts/controllers/transactions')
-const TxGasUtils = require('../../app/scripts/controllers/transactions/tx-gas-utils')
-const { createTestProviderTools, getTestAccounts } = require('../stub/provider')
+const TransactionController = require('../../../../../app/scripts/controllers/transactions')
+const TxGasUtils = require('../../../../../app/scripts/controllers/transactions/tx-gas-utils')
+const { createTestProviderTools, getTestAccounts } = require('../../../../stub/provider')
const noop = () => true
const currentNetworkId = 42
@@ -40,36 +40,6 @@ describe('Transaction Controller', function () {
txController.nonceTracker.getNonceLock = () => Promise.resolve({ nextNonce: 0, releaseLock: noop })
})
- describe('#isNonceTaken', function () {
- it('should return true', function (done) {
- txController.txStateManager._saveTxList([
- { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
- { id: 2, status: 'confirmed', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
- { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
- ])
- txController.isNonceTaken({txParams: {nonce:0, from:'0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'}})
- .then((isNonceTaken) => {
- assert(isNonceTaken)
- done()
- }).catch(done)
-
- })
- it('should return false', function (done) {
- txController.txStateManager._saveTxList([
- { id: 1, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
- { id: 2, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
- { id: 3, status: 'submitted', metamaskNetworkId: currentNetworkId, txParams: {nonce: 0, from: '0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'} },
- ])
-
- txController.isNonceTaken({txParams: {nonce:0, from:'0x8ACCE2391C0d510a6C5E5D8f819A678F79B7E675'}})
- .then((isNonceTaken) => {
- assert(!isNonceTaken)
- done()
- }).catch(done)
-
- })
- })
-
describe('#getState', function () {
it('should return a state object with the right keys and datat types', function () {
const exposedState = txController.getState()
diff --git a/test/unit/tx-gas-util-test.js b/test/unit/app/controllers/transactions/tx-gas-util-test.js
index c1d5966da..d1ee86033 100644
--- a/test/unit/tx-gas-util-test.js
+++ b/test/unit/app/controllers/transactions/tx-gas-util-test.js
@@ -3,8 +3,8 @@ const Transaction = require('ethereumjs-tx')
const BN = require('bn.js')
-const { hexToBn, bnToHex } = require('../../app/scripts/lib/util')
-const TxUtils = require('../../app/scripts/controllers/transactions/tx-gas-utils')
+const { hexToBn, bnToHex } = require('../../../../../app/scripts/lib/util')
+const TxUtils = require('../../../../../app/scripts/controllers/transactions/tx-gas-utils')
describe('txUtils', function () {
diff --git a/test/unit/tx-helper-test.js b/test/unit/app/controllers/transactions/tx-helper-test.js
index cc6543c30..ce54ef483 100644
--- a/test/unit/tx-helper-test.js
+++ b/test/unit/app/controllers/transactions/tx-helper-test.js
@@ -1,5 +1,5 @@
const assert = require('assert')
-const txHelper = require('../../ui/lib/tx-helper')
+const txHelper = require('../../../../../ui/lib/tx-helper')
describe('txHelper', function () {
it('always shows the oldest tx first', function () {
diff --git a/test/unit/app/controllers/transactions/tx-state-history-helper-test.js b/test/unit/app/controllers/transactions/tx-state-history-helper-test.js
new file mode 100644
index 000000000..f4c3a6be1
--- /dev/null
+++ b/test/unit/app/controllers/transactions/tx-state-history-helper-test.js
@@ -0,0 +1,129 @@
+const assert = require('assert')
+const txStateHistoryHelper = require('../../../../../app/scripts/controllers/transactions/lib/tx-state-history-helper')
+const testVault = require('../../../../data/v17-long-history.json')
+
+describe ('Transaction state history helper', function () {
+
+ describe('#snapshotFromTxMeta', function () {
+ it('should clone deep', function () {
+ const input = {
+ foo: {
+ bar: {
+ bam: 'baz'
+ }
+ }
+ }
+ const output = txStateHistoryHelper.snapshotFromTxMeta(input)
+ assert('foo' in output, 'has a foo key')
+ assert('bar' in output.foo, 'has a bar key')
+ assert('bam' in output.foo.bar, 'has a bar key')
+ assert.equal(output.foo.bar.bam, 'baz', 'has a baz value')
+ })
+
+ it('should remove the history key', function () {
+ const input = { foo: 'bar', history: 'remembered' }
+ const output = txStateHistoryHelper.snapshotFromTxMeta(input)
+ assert(typeof output.history, 'undefined', 'should remove history')
+ })
+ })
+
+ describe('#migrateFromSnapshotsToDiffs', function () {
+ it('migrates history to diffs and can recover original values', function () {
+ testVault.data.TransactionController.transactions.forEach((tx, index) => {
+ const newHistory = txStateHistoryHelper.migrateFromSnapshotsToDiffs(tx.history)
+ newHistory.forEach((newEntry, index) => {
+ if (index === 0) {
+ assert.equal(Array.isArray(newEntry), false, 'initial history item IS NOT a json patch obj')
+ } else {
+ assert.equal(Array.isArray(newEntry), true, 'non-initial history entry IS a json patch obj')
+ }
+ const oldEntry = tx.history[index]
+ const historySubset = newHistory.slice(0, index + 1)
+ const reconstructedValue = txStateHistoryHelper.replayHistory(historySubset)
+ assert.deepEqual(oldEntry, reconstructedValue, 'was able to reconstruct old entry from diffs')
+ })
+ })
+ })
+ })
+
+ describe('#replayHistory', function () {
+ it('replaying history does not mutate the original obj', function () {
+ const initialState = { test: true, message: 'hello', value: 1 }
+ const diff1 = [{
+ "op": "replace",
+ "path": "/message",
+ "value": "haay",
+ }]
+ const diff2 = [{
+ "op": "replace",
+ "path": "/value",
+ "value": 2,
+ }]
+ const history = [initialState, diff1, diff2]
+
+ const beforeStateSnapshot = JSON.stringify(initialState)
+ const latestState = txStateHistoryHelper.replayHistory(history)
+ const afterStateSnapshot = JSON.stringify(initialState)
+
+ assert.notEqual(initialState, latestState, 'initial state is not the same obj as the latest state')
+ assert.equal(beforeStateSnapshot, afterStateSnapshot, 'initial state is not modified during run')
+ })
+ })
+
+ describe('#generateHistoryEntry', function () {
+
+ function generateHistoryEntryTest(note) {
+
+ const prevState = {
+ someValue: 'value 1',
+ foo: {
+ bar: {
+ bam: 'baz'
+ }
+ }
+ }
+
+ const nextState = {
+ newPropRoot: 'new property - root',
+ someValue: 'value 2',
+ foo: {
+ newPropFirstLevel: 'new property - first level',
+ bar: {
+ bam: 'baz'
+ }
+ }
+ }
+
+ const before = new Date().getTime()
+ const result = txStateHistoryHelper.generateHistoryEntry(prevState, nextState, note)
+ const after = new Date().getTime()
+
+ assert.ok(Array.isArray(result))
+ assert.equal(result.length, 3)
+
+ const expectedEntry1 = { op: 'add', path: '/foo/newPropFirstLevel', value: 'new property - first level' }
+ assert.equal(result[0].op, expectedEntry1.op)
+ assert.equal(result[0].path, expectedEntry1.path)
+ assert.equal(result[0].value, expectedEntry1.value)
+ assert.equal(result[0].value, expectedEntry1.value)
+ if (note)
+ assert.equal(result[0].note, note)
+
+ assert.ok(result[0].timestamp >= before && result[0].timestamp <= after)
+
+ const expectedEntry2 = { op: 'replace', path: '/someValue', value: 'value 2' }
+ assert.deepEqual(result[1], expectedEntry2)
+
+ const expectedEntry3 = { op: 'add', path: '/newPropRoot', value: 'new property - root' }
+ assert.deepEqual(result[2], expectedEntry3)
+ }
+
+ it('should generate history entries', function () {
+ generateHistoryEntryTest()
+ })
+
+ it('should add note to first entry', function () {
+ generateHistoryEntryTest('custom note')
+ })
+ })
+}) \ No newline at end of file
diff --git a/test/unit/tx-state-manager-test.js b/test/unit/app/controllers/transactions/tx-state-manager-test.js
index e5fe68d0b..20bc08b94 100644
--- a/test/unit/tx-state-manager-test.js
+++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js
@@ -1,8 +1,8 @@
const assert = require('assert')
const clone = require('clone')
const ObservableStore = require('obs-store')
-const TxStateManager = require('../../app/scripts/controllers/transactions/tx-state-manager')
-const txStateHistoryHelper = require('../../app/scripts/controllers/transactions/lib/tx-state-history-helper')
+const TxStateManager = require('../../../../../app/scripts/controllers/transactions/tx-state-manager')
+const txStateHistoryHelper = require('../../../../../app/scripts/controllers/transactions/lib/tx-state-history-helper')
const noop = () => true
describe('TransactionStateManager', function () {
@@ -176,14 +176,21 @@ describe('TransactionStateManager', function () {
assert.deepEqual(updatedTx.history[0], txStateHistoryHelper.snapshotFromTxMeta(updatedTx), 'first history item is initial state')
// modify value and updateTx
updatedTx.txParams.gasPrice = desiredGasPrice
+ const before = new Date().getTime()
txStateManager.updateTx(updatedTx)
+ const after = new Date().getTime()
// check updated value
const result = txStateManager.getTx('1')
assert.equal(result.txParams.gasPrice, desiredGasPrice, 'gas price updated')
// validate history was updated
assert.equal(result.history.length, 2, 'two history items (initial + diff)')
+ assert.equal(result.history[1].length, 1, 'two history state items (initial + diff)')
+
const expectedEntry = { op: 'replace', path: '/txParams/gasPrice', value: desiredGasPrice }
- assert.deepEqual(result.history[1], [expectedEntry], 'two history items (initial + diff)')
+ assert.deepEqual(result.history[1][0].op, expectedEntry.op, 'two history items (initial + diff) operation')
+ assert.deepEqual(result.history[1][0].path, expectedEntry.path, 'two history items (initial + diff) path')
+ assert.deepEqual(result.history[1][0].value, expectedEntry.value, 'two history items (initial + diff) value')
+ assert.ok(result.history[1][0].timestamp >= before && result.history[1][0].timestamp <= after)
})
})
diff --git a/test/unit/tx-utils-test.js b/test/unit/app/controllers/transactions/tx-utils-test.js
index be16225ba..115127f85 100644
--- a/test/unit/tx-utils-test.js
+++ b/test/unit/app/controllers/transactions/tx-utils-test.js
@@ -1,5 +1,5 @@
const assert = require('assert')
-const txUtils = require('../../app/scripts/controllers/transactions/lib/util')
+const txUtils = require('../../../../../app/scripts/controllers/transactions/lib/util')
describe('txUtils', function () {
diff --git a/test/unit/edge-encryptor-test.js b/test/unit/app/edge-encryptor-test.js
index d3f014d74..cc9777389 100644
--- a/test/unit/edge-encryptor-test.js
+++ b/test/unit/app/edge-encryptor-test.js
@@ -1,6 +1,6 @@
const assert = require('assert')
-const EdgeEncryptor = require('../../app/scripts/edge-encryptor')
+const EdgeEncryptor = require('../../../app/scripts/edge-encryptor')
var password = 'passw0rd1'
var data = 'some random data'
diff --git a/test/unit/message-manager-test.js b/test/unit/app/message-manager-test.js
index 5e7039841..36ef6c29f 100644
--- a/test/unit/message-manager-test.js
+++ b/test/unit/app/message-manager-test.js
@@ -1,5 +1,5 @@
const assert = require('assert')
-const MessageManager = require('../../app/scripts/lib/message-manager')
+const MessageManager = require('../../../app/scripts/lib/message-manager')
describe('Message Manager', function () {
let messageManager
diff --git a/test/unit/nodeify-test.js b/test/unit/app/nodeify-test.js
index c7b127889..901603c8b 100644
--- a/test/unit/nodeify-test.js
+++ b/test/unit/app/nodeify-test.js
@@ -1,5 +1,5 @@
const assert = require('assert')
-const nodeify = require('../../app/scripts/lib/nodeify')
+const nodeify = require('../../../app/scripts/lib/nodeify')
describe('nodeify', function () {
var obj = {
diff --git a/test/unit/pending-balance-test.js b/test/unit/app/pending-balance-test.js
index dc4c1c3e4..1418e4a4e 100644
--- a/test/unit/pending-balance-test.js
+++ b/test/unit/app/pending-balance-test.js
@@ -1,6 +1,6 @@
const assert = require('assert')
-const PendingBalanceCalculator = require('../../app/scripts/lib/pending-balance-calculator')
-const MockTxGen = require('../lib/mock-tx-gen')
+const PendingBalanceCalculator = require('../../../app/scripts/lib/pending-balance-calculator')
+const MockTxGen = require('../../lib/mock-tx-gen')
const BN = require('ethereumjs-util').BN
let providerResultStub = {}
diff --git a/test/unit/personal-message-manager-test.js b/test/unit/app/personal-message-manager-test.js
index ec2f9a4d1..b07167bff 100644
--- a/test/unit/personal-message-manager-test.js
+++ b/test/unit/app/personal-message-manager-test.js
@@ -1,6 +1,6 @@
const assert = require('assert')
-const PersonalMessageManager = require('../../app/scripts/lib/personal-message-manager')
+const PersonalMessageManager = require('../../../app/scripts/lib/personal-message-manager')
describe('Personal Message Manager', function () {
let messageManager
diff --git a/test/unit/seed-phrase-verifier-test.js b/test/unit/app/seed-phrase-verifier-test.js
index 4e314806b..b0da534da 100644
--- a/test/unit/seed-phrase-verifier-test.js
+++ b/test/unit/app/seed-phrase-verifier-test.js
@@ -1,9 +1,9 @@
const assert = require('assert')
const clone = require('clone')
const KeyringController = require('eth-keyring-controller')
-const firstTimeState = require('../../app/scripts/first-time-state')
-const seedPhraseVerifier = require('../../app/scripts/lib/seed-phrase-verifier')
-const mockEncryptor = require('../lib/mock-encryptor')
+const firstTimeState = require('../../../app/scripts/first-time-state')
+const seedPhraseVerifier = require('../../../app/scripts/lib/seed-phrase-verifier')
+const mockEncryptor = require('../../lib/mock-encryptor')
describe('SeedPhraseVerifier', function () {
diff --git a/test/unit/util-test.js b/test/unit/app/util-test.js
index 6da185b2c..670bc4d22 100644
--- a/test/unit/util-test.js
+++ b/test/unit/app/util-test.js
@@ -1,5 +1,5 @@
const assert = require('assert')
-const { sufficientBalance } = require('../../app/scripts/lib/util')
+const { sufficientBalance } = require('../../../app/scripts/lib/util')
describe('SufficientBalance', function () {
diff --git a/test/unit/metamask-controller-test.js b/test/unit/metamask-controller-test.js
deleted file mode 100644
index 18c3f9ab9..000000000
--- a/test/unit/metamask-controller-test.js
+++ /dev/null
@@ -1,120 +0,0 @@
-const assert = require('assert')
-const sinon = require('sinon')
-const clone = require('clone')
-const nock = require('nock')
-const MetaMaskController = require('../../app/scripts/metamask-controller')
-const blacklistJSON = require('../stub/blacklist')
-const firstTimeState = require('../../app/scripts/first-time-state')
-
-const DEFAULT_LABEL = 'Account 1'
-const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'
-const TEST_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'
-const TEST_SEED_ALT = 'setup olympic issue mobile velvet surge alcohol burger horse view reopen gentle'
-const TEST_ADDRESS_ALT = '0xc42edfcc21ed14dda456aa0756c153f7985d8813'
-
-describe('MetaMaskController', function () {
- let metamaskController
- const sandbox = sinon.sandbox.create()
- const noop = () => { }
-
- beforeEach(function () {
-
- nock('https://api.infura.io')
- .persist()
- .get('/v2/blacklist')
- .reply(200, blacklistJSON)
-
- nock('https://api.infura.io')
- .persist()
- .get(/.*/)
- .reply(200)
-
- metamaskController = new MetaMaskController({
- showUnapprovedTx: noop,
- encryptor: {
- encrypt: function (password, object) {
- this.object = object
- return Promise.resolve()
- },
- decrypt: function () {
- return Promise.resolve(this.object)
- },
- },
- initState: clone(firstTimeState),
- })
- sandbox.spy(metamaskController.keyringController, 'createNewVaultAndKeychain')
- sandbox.spy(metamaskController.keyringController, 'createNewVaultAndRestore')
- })
-
- afterEach(function () {
- nock.cleanAll()
- sandbox.restore()
- })
-
- describe('#getGasPrice', function () {
- it('gives the 50th percentile lowest accepted gas price from recentBlocksController', async function () {
- const realRecentBlocksController = metamaskController.recentBlocksController
- metamaskController.recentBlocksController = {
- store: {
- getState: () => {
- return {
- recentBlocks: [
- { gasPrices: [ '0x3b9aca00', '0x174876e800'] },
- { gasPrices: [ '0x3b9aca00', '0x174876e800'] },
- { gasPrices: [ '0x174876e800', '0x174876e800' ]},
- { gasPrices: [ '0x174876e800', '0x174876e800' ]},
- ],
- }
- },
- },
- }
-
- const gasPrice = metamaskController.getGasPrice()
- assert.equal(gasPrice, '0x3b9aca00', 'accurately estimates 50th percentile accepted gas price')
-
- metamaskController.recentBlocksController = realRecentBlocksController
- })
- })
-
- describe('#createNewVaultAndKeychain', function () {
- it('can only create new vault on keyringController once', async function () {
- const selectStub = sandbox.stub(metamaskController, 'selectFirstIdentity')
-
- const password = 'a-fake-password'
-
- await metamaskController.createNewVaultAndKeychain(password)
- await metamaskController.createNewVaultAndKeychain(password)
-
- assert(metamaskController.keyringController.createNewVaultAndKeychain.calledOnce)
-
- selectStub.reset()
- })
- })
-
- describe('#createNewVaultAndRestore', function () {
- it('should be able to call newVaultAndRestore despite a mistake.', async function () {
- const password = 'what-what-what'
- await metamaskController.createNewVaultAndRestore(password, TEST_SEED.slice(0, -1)).catch((e) => null)
- await metamaskController.createNewVaultAndRestore(password, TEST_SEED)
-
- assert(metamaskController.keyringController.createNewVaultAndRestore.calledTwice)
- })
-
- it('should clear previous identities after vault restoration', async () => {
- await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED)
- assert.deepEqual(metamaskController.getState().identities, {
- [TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL },
- })
-
- await metamaskController.keyringController.saveAccountLabel(TEST_ADDRESS, 'Account Foo')
- assert.deepEqual(metamaskController.getState().identities, {
- [TEST_ADDRESS]: { address: TEST_ADDRESS, name: 'Account Foo' },
- })
-
- await metamaskController.createNewVaultAndRestore('foobar1337', TEST_SEED_ALT)
- assert.deepEqual(metamaskController.getState().identities, {
- [TEST_ADDRESS_ALT]: { address: TEST_ADDRESS_ALT, name: DEFAULT_LABEL },
- })
- })
- })
-})
diff --git a/test/unit/migrations/026-test.js b/test/unit/migrations/026-test.js
new file mode 100644
index 000000000..b3f5470cf
--- /dev/null
+++ b/test/unit/migrations/026-test.js
@@ -0,0 +1,41 @@
+const assert = require('assert')
+const migration26 = require('../../../app/scripts/migrations/026')
+const oldStorage = {
+ 'meta': {'version': 25},
+ 'data': {
+ 'PreferencesController': {},
+ 'KeyringController': {
+ 'walletNicknames': {
+ '0x1e77e2': 'Test Account 1',
+ '0x7e57e2': 'Test Account 2',
+ },
+ },
+ },
+}
+
+describe('migration #26', () => {
+ it('should move the identities from KeyringController', (done) => {
+ migration26.migrate(oldStorage)
+ .then((newStorage) => {
+ const identities = newStorage.data.PreferencesController.identities
+ assert.deepEqual(identities, {
+ '0x1e77e2': {name: 'Test Account 1', address: '0x1e77e2'},
+ '0x7e57e2': {name: 'Test Account 2', address: '0x7e57e2'},
+ })
+ assert.strictEqual(newStorage.data.KeyringController.walletNicknames, undefined)
+ done()
+ })
+ .catch(done)
+ })
+
+ it('should successfully migrate first time state', (done) => {
+ migration26.migrate({
+ meta: {},
+ data: require('../../../app/scripts/first-time-state'),
+ })
+ .then((migratedData) => {
+ assert.equal(migratedData.meta.version, migration26.version)
+ done()
+ }).catch(done)
+ })
+})
diff --git a/test/unit/migrations-test.js b/test/unit/migrations/migrations-test.js
index 5bad25a45..50afd9c2e 100644
--- a/test/unit/migrations-test.js
+++ b/test/unit/migrations/migrations-test.js
@@ -1,22 +1,22 @@
const assert = require('assert')
const path = require('path')
-const wallet1 = require(path.join('..', 'lib', 'migrations', '001.json'))
-const vault4 = require(path.join('..', 'lib', 'migrations', '004.json'))
+const wallet1 = require(path.join('..', '..', 'lib', 'migrations', '001.json'))
+const vault4 = require(path.join('..', '..', 'lib', 'migrations', '004.json'))
let vault5, vault6, vault7, vault8, vault9 // vault10, vault11
-const migration2 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '002'))
-const migration3 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '003'))
-const migration4 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '004'))
-const migration5 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '005'))
-const migration6 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '006'))
-const migration7 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '007'))
-const migration8 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '008'))
-const migration9 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '009'))
-const migration10 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '010'))
-const migration11 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '011'))
-const migration12 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '012'))
-const migration13 = require(path.join('..', '..', 'app', 'scripts', 'migrations', '013'))
+const migration2 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '002'))
+const migration3 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '003'))
+const migration4 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '004'))
+const migration5 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '005'))
+const migration6 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '006'))
+const migration7 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '007'))
+const migration8 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '008'))
+const migration9 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '009'))
+const migration10 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '010'))
+const migration11 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '011'))
+const migration12 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '012'))
+const migration13 = require(path.join('..', '..', '..', 'app', 'scripts', 'migrations', '013'))
const oldTestRpc = 'https://rawtestrpc.metamask.io/'
diff --git a/test/unit/migrator-test.js b/test/unit/migrations/migrator-test.js
index 4404e1dc4..a9374dff1 100644
--- a/test/unit/migrator-test.js
+++ b/test/unit/migrations/migrator-test.js
@@ -1,7 +1,7 @@
const assert = require('assert')
const clone = require('clone')
-const Migrator = require('../../app/scripts/lib/migrator/')
-const liveMigrations = require('../../app/scripts/migrations/')
+const Migrator = require('../../../app/scripts/lib/migrator/')
+const liveMigrations = require('../../../app/scripts/migrations/')
const stubMigrations = [
{
version: 1,
@@ -33,7 +33,7 @@ const versionedData = {meta: {version: 0}, data: {hello: 'world'}}
const firstTimeState = {
meta: { version: 0 },
- data: require('../../app/scripts/first-time-state'),
+ data: require('../../../app/scripts/first-time-state'),
}
describe('Migrator', () => {
diff --git a/test/unit/nameForAccount_test.js b/test/unit/nameForAccount_test.js
index 32af49e9d..9bb02c6bc 100644
--- a/test/unit/nameForAccount_test.js
+++ b/test/unit/nameForAccount_test.js
@@ -6,7 +6,7 @@ var contractNamer = require(path.join(__dirname, '..', '..', 'old-ui', 'lib', 'c
describe('contractNamer', function () {
beforeEach(function () {
- this.sinon = sinon.sandbox.create()
+ this.sinon = sinon.createSandbox()
})
afterEach(function () {
diff --git a/test/unit/preferences-controller-test.js b/test/unit/preferences-controller-test.js
deleted file mode 100644
index 9fb5e4251..000000000
--- a/test/unit/preferences-controller-test.js
+++ /dev/null
@@ -1,48 +0,0 @@
-const assert = require('assert')
-const PreferencesController = require('../../app/scripts/controllers/preferences')
-
-describe('preferences controller', function () {
- let preferencesController
-
- before(() => {
- preferencesController = new PreferencesController()
- })
-
- describe('addToken', function () {
- it('should add that token to its state', async function () {
- const address = '0xabcdef1234567'
- const symbol = 'ABBR'
- const decimals = 5
-
- await preferencesController.addToken(address, symbol, decimals)
-
- const tokens = preferencesController.getTokens()
- assert.equal(tokens.length, 1, 'one token added')
-
- const added = tokens[0]
- assert.equal(added.address, address, 'set address correctly')
- assert.equal(added.symbol, symbol, 'set symbol correctly')
- assert.equal(added.decimals, decimals, 'set decimals correctly')
- })
-
- it('should allow updating a token value', async function () {
- const address = '0xabcdef1234567'
- const symbol = 'ABBR'
- const decimals = 5
-
- await preferencesController.addToken(address, symbol, decimals)
-
- const newDecimals = 6
- await preferencesController.addToken(address, symbol, newDecimals)
-
- const tokens = preferencesController.getTokens()
- assert.equal(tokens.length, 1, 'one token added')
-
- const added = tokens[0]
- assert.equal(added.address, address, 'set address correctly')
- assert.equal(added.symbol, symbol, 'set symbol correctly')
- assert.equal(added.decimals, newDecimals, 'updated decimals correctly')
- })
- })
-})
-
diff --git a/test/unit/reducers/unlock_vault_test.js b/test/unit/reducers/unlock_vault_test.js
index 2b7d70b2c..d66e8edbb 100644
--- a/test/unit/reducers/unlock_vault_test.js
+++ b/test/unit/reducers/unlock_vault_test.js
@@ -10,7 +10,7 @@ var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'redu
describe('#unlockMetamask(selectedAccount)', function () {
beforeEach(function () {
// sinon allows stubbing methods that are easily verified
- this.sinon = sinon.sandbox.create()
+ this.sinon = sinon.createSandbox()
})
afterEach(function () {
diff --git a/test/unit/tx-state-history-helper-test.js b/test/unit/tx-state-history-helper-test.js
deleted file mode 100644
index 35e9ef188..000000000
--- a/test/unit/tx-state-history-helper-test.js
+++ /dev/null
@@ -1,26 +0,0 @@
-const assert = require('assert')
-const clone = require('clone')
-const txStateHistoryHelper = require('../../app/scripts/controllers/transactions/lib/tx-state-history-helper')
-
-describe('deepCloneFromTxMeta', function () {
- it('should clone deep', function () {
- const input = {
- foo: {
- bar: {
- bam: 'baz'
- }
- }
- }
- const output = txStateHistoryHelper.snapshotFromTxMeta(input)
- assert('foo' in output, 'has a foo key')
- assert('bar' in output.foo, 'has a bar key')
- assert('bam' in output.foo.bar, 'has a bar key')
- assert.equal(output.foo.bar.bam, 'baz', 'has a baz value')
- })
-
- it('should remove the history key', function () {
- const input = { foo: 'bar', history: 'remembered' }
- const output = txStateHistoryHelper.snapshotFromTxMeta(input)
- assert(typeof output.history, 'undefined', 'should remove history')
- })
-})
diff --git a/test/unit/tx-state-history-helper.js b/test/unit/tx-state-history-helper.js
deleted file mode 100644
index 35f7dac57..000000000
--- a/test/unit/tx-state-history-helper.js
+++ /dev/null
@@ -1,46 +0,0 @@
-const assert = require('assert')
-const txStateHistoryHelper = require('../../app/scripts/controllers/transactions/lib/tx-state-history-helper')
-const testVault = require('../data/v17-long-history.json')
-
-
-describe('tx-state-history-helper', function () {
- it('migrates history to diffs and can recover original values', function () {
- testVault.data.TransactionController.transactions.forEach((tx, index) => {
- const newHistory = txStateHistoryHelper.migrateFromSnapshotsToDiffs(tx.history)
- newHistory.forEach((newEntry, index) => {
- if (index === 0) {
- assert.equal(Array.isArray(newEntry), false, 'initial history item IS NOT a json patch obj')
- } else {
- assert.equal(Array.isArray(newEntry), true, 'non-initial history entry IS a json patch obj')
- }
- const oldEntry = tx.history[index]
- const historySubset = newHistory.slice(0, index + 1)
- const reconstructedValue = txStateHistoryHelper.replayHistory(historySubset)
- assert.deepEqual(oldEntry, reconstructedValue, 'was able to reconstruct old entry from diffs')
- })
- })
- })
-
- it('replaying history does not mutate the original obj', function () {
- const initialState = { test: true, message: 'hello', value: 1 }
- const diff1 = [{
- "op": "replace",
- "path": "/message",
- "value": "haay",
- }]
- const diff2 = [{
- "op": "replace",
- "path": "/value",
- "value": 2,
- }]
- const history = [initialState, diff1, diff2]
-
- const beforeStateSnapshot = JSON.stringify(initialState)
- const latestState = txStateHistoryHelper.replayHistory(history)
- const afterStateSnapshot = JSON.stringify(initialState)
-
- assert.notEqual(initialState, latestState, 'initial state is not the same obj as the latest state')
- assert.equal(beforeStateSnapshot, afterStateSnapshot, 'initial state is not modified during run')
- })
-
-})
diff --git a/test/unit/util_test.js b/test/unit/util_test.js
index 59048975a..39473854f 100644
--- a/test/unit/util_test.js
+++ b/test/unit/util_test.js
@@ -10,7 +10,7 @@ describe('util', function () {
for (var i = 0; i < 18; i++) { ethInWei += '0' }
beforeEach(function () {
- this.sinon = sinon.sandbox.create()
+ this.sinon = sinon.createSandbox()
})
afterEach(function () {